Compare commits

...

145 Commits

Author SHA1 Message Date
Electron Bot
25e4a9431c Bump v11.0.0-nightly.20200604 2020-06-04 08:32:18 -07:00
Milan Burda
3fa4299939 fix: use acceptLanguages argument in session.setUserAgent() (#23944) 2020-06-04 13:05:37 +02:00
Cheng Zhao
90caa5eac9 docs: remove confusing notes on Node (#23929)
* docs: remove confusing notes on Node

* Update docs/tutorial/first-app.md

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

Co-authored-by: Mark Lee <malept@users.noreply.github.com>
2020-06-03 20:00:52 -07:00
Samuel Attard
b1adbf7fd7 build: fix filenames autogen with new BUILDFLAG syntax (#23952) 2020-06-03 15:46:59 -07:00
Cheng Zhao
2fadb73032 fix: destroy GetSize callback at last (#23930) 2020-06-03 11:04:30 -07:00
Shelley Vohr
ac81a39e09 fix: compensate for lazy-loaded circular deps (#23890) 2020-06-03 10:29:08 -07:00
Electron Bot
83247c48c3 Bump v11.0.0-nightly.20200603 2020-06-03 08:31:46 -07:00
Cheng Zhao
5de6adfb84 test: load page with some content when testing extension (#23901)
* test: load page with some content when testing extension

* test: use dom-ready to wait for page loaded with extension
2020-06-03 16:56:28 +09:00
Samuel Attard
d8594f7a78 fix: restore original GTK/appindicator implementation of tray icons (#23674) 2020-06-02 17:00:20 -07:00
Samuel Attard
087567655a fix: correctly support the --inspect-brk-node flag (#23903) 2020-06-02 15:02:54 -07:00
Robo
512e1541c6 fix: default to NTLM v2 in the network service for POSIX platforms (#23846)
* fix: default to NTLM v2 in the network service

* chore: update patch details
2020-06-02 12:58:00 -07:00
Samuel Attard
c36981da8b docs: default of allowRendererProcessReuse is true (#23888) 2020-06-02 11:09:20 -07:00
Samuel Attard
d3fa5ed1e8 docs: move protocol-ns to protocol.md (#23883)
* docs: move protocol-ns to protocol.md

* chore: fix up tests and implement missing pieces required for tests
2020-06-02 09:46:18 -07:00
Electron Bot
edc5050a2e Bump v11.0.0-nightly.20200602 2020-06-02 08:32:11 -07:00
Jeremy Apthorp
a5efc387c7 chore: note quiet period in PR template. (#23889) 2020-06-02 09:36:09 -04:00
Samuel Attard
0062b126b4 chore: update patches (#23902) 2020-06-02 03:34:52 -07:00
Samuel Attard
969f46a48f chore: remove IPC hiddens (#23720) 2020-06-02 02:33:06 -07:00
Samuel Attard
c6f4573a13 perf: lazily load some modules in sandbox mode (#23856) 2020-06-02 02:32:32 -07:00
Biru Mohanathas
95037a7d2a fix: Make the --disable-color-correct-rendering switch work again (#23787)
This regressed once again in Electron 8 due to Chromium changes.

Test Plan:

- Confirm that test case from https://github.com/electron/electron/pull/15898#issuecomment-443191770 now works

Notes: Fix disabling color correct rendering with `--disable-color-correct-rendering`
2020-06-02 16:31:33 +09:00
Wojciech Krol
5218a6e6ab fix: notify URLLoaderClient about redirect inside intercepted protocol's handler (#23742)
* fix: notify URLLoaderClient about redirect inside intercepted protocol's handler

* fix: update new_request's site_for_coookies

* fix: Unound client, so it an be passed to sub-methods
2020-06-02 14:20:34 +09:00
Cheng Zhao
5918dd6e65 test: wait for beforeunload handler to be installed (#23874) 2020-06-02 11:32:39 +09:00
Samuel Attard
fbf397e15d fix: add patch to prevent crash during frame swap with ctx isolation enabled (#23684) 2020-06-01 18:02:30 -07:00
Samuel Attard
066b8c5ab3 fix: expose electron/common and electron/renderer modules in sandboxed preloads (#23857) 2020-06-01 17:37:02 -07:00
Samuel Attard
634ab45095 build: make electron renderer init scripts profilable (#23855)
The devtools profiler is not attached at the point we run out init scripts (or our apps preload scripts), we do not really want to change when we run these init scripts but for when a dev is doing performance work it makes sense to give them an option to make the devtools profiler actually work on both our init scripts and their preload script.  This PR adds that logic behind an environment variable ELECTRON_PROFILE_INIT_SCRIPTS.
2020-06-01 16:08:34 -07:00
Electron Bot
a4de915b74 chore: bump chromium to d66c2e32380bf5d1eb5e1fe37faef (master) (#23791)
* chore: bump chromium in DEPS to db7d7b3e7cb2bc925f2abfde526280cfdfc21a41

* Update patches

* chore: bump chromium in DEPS to 5613e1b99a44fcbe22f3910f803ca76903a77ec1

* Update patches

* Network service: Remove primary_network_context bool.

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

* WebContentsObserver now implements OnRendererResponsive

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

* update patches

* Fixup printing patch

* chore: bump chromium in DEPS to e387b972cdd7160c416fa6c64a724e2258aa0218

* update patches

* [printing] Move PrintHostMsg_DidPrintContent_Params to print.mojom

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

* [XProto] Move items from ::x11::XProto to ::x11

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

* revert Add IChromeAccessible

This was added in https://chromium-review.googlesource.com/c/chromium/src/+/2206224 but it breaks WOA builds because third_party/win_build_output/midl/ui/accessibility/platform/arm64 does not exist. The link above says that the new interface is behind a feature flag which is disabled by default so it is safe to remove for now.

* rebaseline ichromeaccessible for Windows arm64

This patch will not be needed once we get the next roll.

* Update to 1b9e01844e8bf1aaafc4a52c0c62af7f56d9637b to get arm64 fix

* update patches

* chore: bump chromium in DEPS to 096aefa04092ea00f7b68d8d19345883f20db3c3

* chore: bump chromium in DEPS to a524a45ffd1d6fd46a7a86138fe2b22df5b6651a

* chore: update patches

* Window Placement: Gate cross-screen fullscreen behavior on permission

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

* chore: add spec for https://crbug.com/1085836

* chore: bump chromium in DEPS to ff6c4f4b826d66c2e32380bf5d1eb5e1fe37faef

* update patches

Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
Co-authored-by: Electron Bot <anonymous@electronjs.org>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
2020-06-01 16:34:34 -04:00
Electron Bot
4a551bde16 Bump v11.0.0-nightly.20200601 2020-06-01 08:32:05 -07:00
Cheng Zhao
b809d104d0 fix: do not use CONTEXT_MENU flag for tray menu (#23843) 2020-06-01 09:57:25 -05:00
Alexey Kuzmin
4133c71105 build: fix for "enable_desktop_capturer = false" (#23864) 2020-06-01 10:13:47 -04:00
Robo
f67aff2704 feat: add V8CacheOptions webpreference (#23842)
* feat: add V8CacheOptions webpreference

* address review comments
2020-05-31 20:09:23 -07:00
Cheng Zhao
aa8d81511f fix: MakeAbsoluteFilePath is a blocking call (#23840) 2020-05-30 10:01:55 -07:00
Samuel Attard
236c1334e3 chore: tsify sandboxed init (#23719) 2020-05-30 02:56:54 -07:00
DeeDeeG
9f21d09dfd docs: remove upgrading-node.md (#23802) 2020-05-29 12:12:35 -07:00
Electron Bot
9dec16d81e Bump v11.0.0-nightly.20200529 2020-05-29 08:31:10 -07:00
John Kleinschmidt
b086197968 fix: use system installed objcopy to copy debug symbols (#23835) 2020-05-29 08:37:02 -04:00
Shelley Vohr
e8ea007104 fix: ensure nativeImage serialization main->renderer (#23759) 2020-05-28 09:43:15 -07:00
Electron Bot
e5da2caa34 Bump v11.0.0-nightly.20200528 2020-05-28 08:32:13 -07:00
Cheng Zhao
a1edf5cf94 Revert "fix: trigger activate event when app is activated via app switcher (#23727)" (#23818)
This reverts commit 2bc85b2579.
2020-05-28 09:53:33 -04:00
Shelley Vohr
6516110c70 fix: volume key globalShortcut registration (#23782) 2020-05-28 08:56:48 -04:00
Alexey Kuzmin
3a7775fa73 test: refactor how spec files are collected (#23774) 2020-05-28 00:21:02 +02:00
Shelley Vohr
5d88d0ee74 fix: only bezel frameless windows (#23779) 2020-05-27 14:07:24 -07:00
Shelley Vohr
7b0a84477a fix: weakly reference MenuModel from MenuController (#23778) 2020-05-27 13:54:52 -07:00
Shelley Vohr
f78504515b fix: handle asynchronous URL loading in bw proxy (#23776) 2020-05-27 13:50:54 -07:00
Cheng Zhao
ca6a415626 fix: pass correct buffer length (#23785) 2020-05-27 10:50:01 -07:00
Electron Bot
f445e0a797 Bump v11.0.0-nightly.20200527 2020-05-27 08:32:31 -07:00
Jeremy Judeaux
204f001c5d feat: add desktopCapturer.getMediaSourceIdForWebContents() to get stream source id from web contents (#22701)
* feat: add desktopCapturer.getMediaSourceIdForWebContents() to get stream source id from web contents

* Cleanup from #22701 PR comments
2020-05-26 16:34:24 -04:00
Electron Bot
dc72f74020 chore: bump chromium to 580fe983e138952553cd6af11ee8b (master) (#23379)
* chore: bump chromium in DEPS to 5ce64b91b4d6a78c97480059f15ff6469fc0918e

* chore: bump chromium in DEPS to e74c73d0000f81b3f40a513176c8d024bba57d28

* chore: bump chromium in DEPS to 501640e650d4657ba63db65fa257e4a899168de7

* chore: bump chromium in DEPS to 00db20e1bc3d77706723a87ada3c1c647a1c37b7

* chore: update patches

* refactor: AddNewContents now takes a target_url

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

* chore: SetHostCleanupFinalizationGroupCallback has been removed from V8

* refactor: use WebInputEvent::Namespace types directly

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

* refactor: FollowRedirect takes in cors exempt headers now

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

* refactor: printing::DuplexMode moved to mojo

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

* refactor: use MessagePortDescriptor instead of raw mojo::MessagePipeHandles

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

* chore: update patches

* chore: bump chromium in DEPS to f1537676d613f3567cfb43adf577b3847fba4bc3

* chore: update patches

* refactor: service_manager::BinderMapWithContext merged into mojo::BinderMap

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

* chore: unused argument removed from ReadAvailableTypes in ui::Clipboard

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

* chore: bump chromium in DEPS to 949888433ab935dd6125c107226a4c9d6da9bf48

* chore: update patches

* update patches

* chore: update sysroots

* chore: bump chromium in DEPS to eaac5b5035fe189b6706e1637122e37134206059

* chore: bump chromium in DEPS to 258b54b903d33dab963adf59016691e6537f8b70

* build: update patches

* refactor: cursor.mojom and cursor_types.mojom moved to //ui/base/cursor/mojom

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

* chore: DesktopWindowTreeHostLinux becomes DesktopWindowTreeHostPlatform

Refs:

* refactor: LogErrorEventDescription moved from ui to x11

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

* chore: update patches

* chore: bump chromium in DEPS to bd06abcfe807d4461683479237cdd920dafa52ca

* chore: bump chromium in DEPS to 1afb0891e56f1e79d204db43ca053a46d0974511

* chore: bump chromium in DEPS to 5cb0f794bf7f155bf8c0a241b94e01c9d90c2744

* chore: bump chromium in DEPS to 37327ba3303234e1a3cd3310ca11a68e81b95123

* update patches

* remove ClientSideDetectionService from browser_process

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

* refactor: shuttle cursor changed event to WebContentsObserver

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

* chore: bump chromium in DEPS to 1d97904bb6936e106df13705208b73e47367c2b9

* avoid IPC crash introduced earlier in the roll

Refs: b67334e781 (diff-607f4e8f7c5686aa09af98c783925babR128)

* remove WebContentsView::SizeContents

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

* chore: bump chromium in DEPS to 87066d1db0546a9de33952ba964e1e42f76f1dae

* update patches

* adapt to //content creating NetworkContexts

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

* WIP temporarily ignore mojo-ified PrintHostMsg_PrintPreviewFailed

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

* add checkout_pgo_profiles to DEPS

* chore: bump chromium in DEPS to a095318bec1dedf580d676f408eaeefdbd9956b1

* add blink's execution_context to electron_lib deps

Refs:
b67334e781#, https://chromium-review.googlesource.com/c/chromium/src/+/1952124

* update patches

* update patches

* refactor: use newly mojo-ified PrintPreviewFailed

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2195343
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* chore: update patches

* chore: remove NOTIFICATION_EXTENSIONS_READY_DEPRECATED

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

* avoid a call to Profile::FromBrowserContext in printing

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

* chore: bump chromium in DEPS to 8f5c6a46861a991e12ffd80554b6bd41a11b0b65

* chore: bump chromium in DEPS to ab66134739ff3b6bdb8de53bbc58a97d1b7b5d8a

* chore: bump chromium in DEPS to dd08df9f6c8d6198f0a7b931ca9e845e27dae033

* chore: update patches

* [printing] Mojofy PrintHostMsg_PrintPreviewCancelled

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

* [printing] Mojofy PrintHostMsg_PrintPreviewInvalidPrinterSettings

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

* [printing] Mojofy PrintHostMsg_DidPrepareDocumentForPreview

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

* fix: inherit base network context params

* fix: use message handle api specific to embedders

* update patches

* chore: update v8 headers

* fixup! avoid a call to Profile::FromBrowserContext in printing

* chore: bump chromium in DEPS to f198bc3276828d992b6202d75a9da6a8363164ea

* chore: update patches

* Remove cors_exempt_headers.h

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

* Supply speech recognition sandbox from service_sandbox_type.h

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

* [content] Remove unused methods from WebContents

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

* [XProto] Replace XAtom with x11::Atom

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

* chore: bump chromium in DEPS to 5df37fabaaed09f3ea511f4ef49203d8ebee7b68

* [UI] Support secondary labels in dropdown menus

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

* chore: update patches

* refactor: GetSublabelAt => GetSecondaryLabelAt

* Revert "[printing] Mojofy PrintHostMsg_DidPrepareDocumentForPreview"

This reverts commit 44ed0892a0c81716229638f17253bbb2cf8f037d.

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

* Unnest CanonicalCookie::CookieInclusionStatus

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

* update print-to-pdf.html with latest html data

https://bugs.chromium.org/p/chromium/issues/detail?id=1085667

* chore: bump chromium in DEPS to 5dfa8d5f706580fe983e138952553cd6af11ee8b

* fix crash in x server when setting window icon

* chore: update patches

* Use a normal return value for WebContentsView::GetContainerBounds.

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

* fix build on windows

* chore: bump chromium in DEPS to 9d15054f4cba060901e43deecf74002f11f47be3

* chore: update patches

* [printing] Mojofy PrintHostMsg_CheckForCancel

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

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: Electron Bot <anonymous@electronjs.org>
Co-authored-by: Andy Locascio <andy@slack-corp.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
2020-05-26 13:06:26 -07:00
Electron Bot
2b39111e30 Bump v11.0.0-nightly.20200526 2020-05-26 08:31:30 -07:00
Lukas Weber
2bc85b2579 fix: trigger activate event when app is activated via app switcher (#23727)
When application is activated thru macOS app switcher (cmd+tab) the
App's activate event is note emitted. The reason is that
`applicationShouldHandleReopen:hasVisibleWindows:` is sent only when app
is activated via Dock. Using `applicationDidBecomeActive:` is handling
all cases properly.

Co-authored-by: Lukas Weber <luweber@microsoft.com>
2020-05-26 10:58:51 -04:00
Cheng Zhao
0a026cde0c test: return after inspector connection is closed (#23763) 2020-05-26 10:47:49 -04:00
John Kleinschmidt
db5cf816b4 ci: deflake WOA tests (#23707) 2020-05-26 10:25:57 -04:00
Cheng Zhao
08f288faf1 test: use WebContents event to test beforeunload (#23699) 2020-05-26 09:21:38 -04:00
Cheng Zhao
0dabd5e8c7 test: more logging in node inspector test (#23746) 2020-05-26 10:20:16 +09:00
Electron Bot
2029ff1903 Bump v11.0.0-nightly.20200525 2020-05-25 08:32:17 -07:00
Samuel Attard
9bc5e98238 chore: tsify more of lib (#23721)
* chore: tsify more of lib

* Update lib/browser/api/session.ts

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

Co-authored-by: Jeremy Apthorp <jeremya@chromium.org>
2020-05-22 12:46:22 -07:00
Shelley Vohr
762f7bcca2 refactor: use typeutils for nativeImage serialization (#23693) 2020-05-22 08:56:57 -07:00
Electron Bot
75847a0c5b Bump v11.0.0-nightly.20200522 2020-05-22 08:32:12 -07:00
Samuel Attard
e3c2ec9f7c chore: remove unused isolated-world-args (#23716) 2020-05-21 20:11:58 -07:00
Cheng Zhao
fdf40ce07a fix: read GTK dark theme setting on Linux (#23678) 2020-05-21 15:41:25 -07:00
Florian Keller
82924679fe docs: Explain console-message parameters (#23661) 2020-05-21 15:39:51 -07:00
Erick Zhao
f373cc770f docs: remove app feedback program doc (#23673) 2020-05-21 15:39:13 -07:00
Shelley Vohr
78d74bf8b4 fix: trigger about panel for about role on on win (#23687) 2020-05-21 15:38:26 -07:00
Samuel Attard
5ed2512881 fix: support 10-x-y in the release notes generator (#23709) 2020-05-21 13:55:27 -07:00
Cheng Zhao
ce77e3327c docs: errors in isolated world are not dispatched (#23653) 2020-05-21 11:56:22 -04:00
mtgto
7b55a70a36 feat: Add Secure Keyboard Entry APIs in macOS (#20678)
* feat: Add Secure Keyboard Entry APIs in macOS

Add methods:
- app.isSecureInputEnabled()
- app.setSecureInputEnabled(enabled)

These enable to prevent other process listens keyboard input events.

* fix: lint error in app.md for #20678

* fix: crash app.setSecureInputEnabled() in password textfield

* fix: export Secure keyboard Entry API to only macOS

* fix: lint error in browser_mac.mm for #20678

* test: add test for app.setSecureKeyboardEntryEnabled in macOS
2020-05-21 11:53:44 -04:00
Jeremy Apthorp
5bdf97e7ae test: hide child windows in webview spec (#23682) 2020-05-21 11:46:17 -04:00
Cheng Zhao
3137d5f011 test: multiple processes may crash in crashReporter test (#23695) 2020-05-21 11:43:47 -04:00
Electron Bot
4114281b62 Bump v10.0.0-nightly.20200521 2020-05-21 08:31:34 -07:00
Shelley Vohr
21a6062a31 docs: document optional scaleFactor param to nativeImage fns (#23671) 2020-05-20 18:52:48 -07:00
Milan Burda
df53816eea feat: expose the desktopCapturer module in the main process (#23548) 2020-05-20 20:25:49 -04:00
Shelley Vohr
4b23a85475 refactor: correctly serialize nativeImage/buffer with typeUtils (#23666)
* refactor: correctly serialize nativeImage/buffer with typeUtils

* test: add serialization specs

* fix: construct from dataURL

* test: test for dataURL specificity
2020-05-20 13:42:42 -07:00
Alexey Kuzmin
33d6a99d40 test: call "expect()" on a correct call stack (#23675) 2020-05-20 22:18:48 +02:00
LuoJinghua
9d851b8791 net: Don't ignore the referer header in net.request (#23386) 2020-05-20 13:28:38 -04:00
Jeremy Apthorp
0a481242f0 fix: wrap EmitWarning with HandleScope (#23667) 2020-05-20 09:44:27 -07:00
Electron Bot
84888bb1f1 Bump v10.0.0-nightly.20200520 2020-05-20 08:31:37 -07:00
Jeremy Apthorp
8de06f0c57 feat: deprecate uncompressed crash uploads (#23598) 2020-05-19 13:47:21 -07:00
Jeremy Apthorp
bca071f428 docs: note no planned breaking changes for v11 (#23638) 2020-05-19 15:39:51 -04:00
Jeremy Apthorp
de44d28c8e refactor: ginify Session (#23569) 2020-05-19 10:18:12 -07:00
Jeremy Apthorp
3f3a760a01 test: bind to 127.0.0.1 in contextBridge spec (#23639) 2020-05-19 10:17:40 -07:00
Jeremy Apthorp
27d7eb3880 docs: remove note about experimental nature of sandbox (#23651) 2020-05-19 10:17:31 -07:00
Jeremy Apthorp
393b637e9e test: attempt to track down "illegal access" error (#23645)
* test: attempt to track down "illegal access" error

* how does electron formed
2020-05-19 12:29:36 -04:00
Electron Bot
33bd218df9 Bump v10.0.0-nightly.20200519 2020-05-19 08:32:19 -07:00
Cheng Zhao
82da234650 test: disable parallel/test-worker-sharedarraybuffer-from-worker-thread (#23652) 2020-05-19 07:57:28 -07:00
Sofia Nguy
ce53c35e1d docs: update currently supported versions for 9.0.0 release (#23510)
* docs: update currently supported versions for 9.0.0 release

* update supported version numbers back to xy format
2020-05-19 09:22:38 -05:00
Sofia Nguy
82f89c8206 docs: update 10.0 stable release date (#23511)
* docs: update 10.0 stable release date

* add bullet for reference to chrome's schedule

* update node version
2020-05-19 09:22:22 -05:00
Cheng Zhao
38a04214e0 fix: make sure hunspell file is not destroyed in UI thread (#23631) 2020-05-19 09:55:23 -04:00
Jeremy Apthorp
01579cc8ed test: add retries to another beforeunload test (#23644) 2020-05-19 11:06:19 +09:00
Jeremy Apthorp
c00103d274 test: fix multiple connections in inspector test (#23648)
* test: fix multiple connections in inspector test

* debug log
2020-05-19 11:05:49 +09:00
John Kleinschmidt
89441caad4 build: save mksnapshot args on Windows (#23634) 2020-05-18 15:42:23 -04:00
Jeremy Apthorp
7e841ceb5c refactor: tsify net module (#23618) 2020-05-18 10:22:48 -07:00
John Kleinschmidt
8879a3db58 ci: use longer mocha timeout on WOA testing (#23633) 2020-05-18 12:33:54 -04:00
Shelley Vohr
ee0f67d541 fix: nativeImage remote serialization (#23543)
We weren't serializing nativeImages properly in the remote module, leading to gin conversion errors when trying to, for example, create a new context menu in the renderer with icons using nativeImage. This fixes that by adding a new special case to handle them.
2020-05-18 09:29:24 -07:00
Electron Bot
eb341b383d Bump v10.0.0-nightly.20200518 2020-05-18 08:31:53 -07:00
Jeremy Apthorp
87a670f74d feat: allow compressing crash uploads on linux (#23597)
* chore: align crash patch with upstream

* feat: allow compressing crash uploads on linux

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-05-18 11:09:50 -04:00
Jeremy Apthorp
8bbb68be79 test: retry beforeunload test (#23576) 2020-05-18 11:04:41 -04:00
Shelley Vohr
75fd9a3496 refactor: improve MoveItemToTrash error description (#23589) 2020-05-17 19:18:34 -07:00
Milan Burda
52b50e6b33 feat: add app render-process-gone event (#23560) 2020-05-17 17:05:05 +02:00
Samuel Attard
9d7ba98209 refactor: remove the RenderFrameFunctionStore and use privates to memory manage (#23592) 2020-05-15 11:57:40 -07:00
Electron Bot
3cf97d5717 Bump v10.0.0-nightly.20200515 2020-05-15 08:32:47 -07:00
Jeremy Apthorp
8b160d57a6 chore: align crash patch with upstream (#23595) 2020-05-14 20:09:02 -07:00
Charles Kerr
2342aaffbd feat: look harder for a commit's pull request. (#23593)
PR numbers are almost always listed parenthetically in the commit message;
but when something is committed manually, it could be missing. This change
uses octokit's listPullRequestsAssociatedWithCommit() as a second approach
to finding a commit's PR.

Last night's Releases WG meeting noted that "re-enable pdf viewer" was
missing from the notes. This PR fixes that omission.
2020-05-14 18:50:39 -05:00
Alexey Kuzmin
092eec8459 build: remove unused header from a patch (#23585) 2020-05-14 09:41:21 -07:00
Electron Bot
db94712227 Bump v10.0.0-nightly.20200514 2020-05-14 08:32:33 -07:00
Milan Burda
4afc756094 feat: add contents.getBackgroundThrottling() + backgroundThrottling property (#21036) 2020-05-14 15:11:45 +02:00
Milan Burda
7656480247 test: remove usage of the remote module from tests (#23571) 2020-05-14 00:33:37 +02:00
Jeremy Apthorp
6282487245 fix: exclude crashpad_handler binary on linux (#23538) 2020-05-13 15:28:12 -07:00
Jeremy Apthorp
e82bb06336 fix: generate symbols for the correct crashpad handler binary (#23537) 2020-05-13 13:54:40 -07:00
Milan Burda
fc468cce3b test: skip remote module related tests when enable_remote_module = false (#23557) 2020-05-13 20:05:44 +02:00
Milan Burda
85fae67966 perf: use type-utils for desktopCapturer.getSources() result serialization (#23549) 2020-05-13 19:05:53 +02:00
Electron Bot
508c7ac4f9 Bump v10.0.0-nightly.20200513 2020-05-13 08:31:51 -07:00
Milan Burda
54b6c06062 fix: expose v8util.createIDWeakMap() regardless of enable_remote_module (#23546) 2020-05-13 12:10:03 +02:00
Samuel Attard
54ff423dac fix: leave behind the unmodified XDG_CURRENT_DESKTOP variable (#23512) 2020-05-12 20:13:53 -07:00
Felix Rieseberg
dcbed18f44 feat: app.getPath('recent') (#23381)
* feat: getPath("recent")

* test: Add a spec and docs

* fix: Integrate feedback

* fix: Handle path change

* chore: Cut SetRecentPath
2020-05-13 11:27:56 +09:00
Samuel Attard
c7b2eb68cf docs: add documentation on how to use the built-in spellchecker (#23508) 2020-05-13 10:25:21 +09:00
Shelley Vohr
3daeec5e3e fix: run Node.js at-exit callbacks in renderer proc (#23419) 2020-05-12 13:09:56 -07:00
John Kleinschmidt
b11836e195 build: use correct v8_context_snapshot_generator in mksnapshot zip (#23536) 2020-05-12 14:52:56 -04:00
Cheng Zhao
16b41dc9ff fix: do not destroy thread in UI thread (#23495) 2020-05-12 10:37:51 -07:00
Milan Burda
ef176ce368 build: fix building with enable_remote_module = false (#23499) 2020-05-12 18:32:04 +02:00
Electron Bot
633f3c2413 Bump v10.0.0-nightly.20200512 2020-05-12 08:31:37 -07:00
Samuel Attard
7bba36a095 chore: add TRACE calls for heavy ctx bridge methods (#23501) 2020-05-11 14:24:43 -07:00
Samuel Attard
34da3bc500 feat: add new render-process-gone event (#23096) 2020-05-11 13:42:24 -07:00
Samuel Attard
7f9b7b2e95 chore: clean up context bridge scopes and add specs for internal bridge (#23334)
* chore: clean up context bridge context scopes

* spec: add specs for internalContextBridge
2020-05-11 13:41:42 -07:00
Samuel Attard
cf635c5fac docs: add document on contextIsolation (#23474)
* docs: add document on contextIsolation

* fix lint

* chore: link ctx isolation doc from security doc
2020-05-11 13:01:32 -07:00
Milan Burda
653c36b8c9 test: skip "handles Promise timeouts correctly" when ELECTRON_RUN_AS_NODE is disabled (#23415) 2020-05-11 14:19:39 -04:00
Samuel Attard
4af5c55c8d chore: add DCHECK to ensure extension_system() is not used for in-memory sessions (#23475) 2020-05-11 11:13:30 -07:00
Robin Dupret
ce4d95b16a docs: badgeCount needs notifications permission on macOS (#23488)
In order for `badgeCount` to properly update the dock icon on
macOS, the application needs to have the permissions to display
notifications.

Cross-refs #22715.
2020-05-11 11:13:17 -07:00
Electron Bot
5951b0ad4b Bump v10.0.0-nightly.20200511 2020-05-11 08:32:21 -07:00
Alexander Prinzhorn
ade8f285d0 Update mime-typed-buffer.md (#23384)
I think this should be aligned with `StringProtocolResponse`. At least the `charset` was missing from the docs.

https://www.electronjs.org/docs/api/protocol#protocolregisterbufferprotocolscheme-handler-completion

>  should be called with either a Buffer object or an object that has the data, mimeType, and charset properties.
2020-05-11 19:00:38 +09:00
Kevin Wang
3866c88aef Fix outdated Cerebral Debugger link (#23427) 2020-05-11 10:53:15 +09:00
Alexey Kuzmin
dc3de49a08 spec: fix conditions for some tests (#23489) 2020-05-11 10:46:45 +09:00
Shelley Vohr
6114518463 fix: NSImageName string conversion (#23467) 2020-05-11 10:24:45 +09:00
Milan Burda
392ea320cf build: allow use of BUILDFLAG directives from within JS code (#20328) 2020-05-11 01:06:07 +02:00
Milan Burda
f9c04449f4 refactor: SystemPreferences::SetUserDefault (#23412) 2020-05-10 00:38:15 +02:00
Pavel Feldman
3c132dc445 chore: handle Browser.close over CDP (#23436) 2020-05-08 16:13:32 -07:00
Samuel Attard
091f45b879 chore: fix linting (#23473) 2020-05-08 11:30:37 -07:00
Samuel Attard
21900fe4f4 fix: do not initialize any extension related logic in OffTheRecord contexts (#22772) 2020-05-08 11:17:28 -07:00
Electron Bot
a3ee61f963 Bump v10.0.0-nightly.20200508 2020-05-08 08:31:44 -07:00
Pavel Feldman
93f6129c80 chore: support --remote-debugging-pipe (#23433) 2020-05-07 21:27:55 -07:00
Jeremy Apthorp
06bf0d08dc fix: crashReporter incompatible with sandbox on Linux (#23265) 2020-05-07 13:31:26 -07:00
Shelley Vohr
fc434f136b fix: multiple extension filters on macOS (#23409) 2020-05-07 08:52:56 -07:00
Electron Bot
a4f701f9a5 Bump v10.0.0-nightly.20200507 2020-05-07 08:32:36 -07:00
Shelley Vohr
ba929b4195 chore: remove obsolete cjs assert patch (#23422) 2020-05-06 22:47:58 -07:00
Robo
a707a3eda3 feat: add enableWebSQL webpreference (#23311)
* feat: add enableWebSQL webpreference

* chore: update indexedDB test
2020-05-06 12:52:59 -07:00
Electron Bot
2a680e107b Bump v10.0.0-nightly.20200506 2020-05-06 08:32:27 -07:00
John Kleinschmidt
b7e4ed2052 build: update sccache for linux (#23418) 2020-05-05 14:38:14 -04:00
szTheory
1611c586ae docs: fix markdown list item formatting error (#23368) 2020-05-05 10:55:27 -07:00
420 changed files with 11212 additions and 7666 deletions

View File

@@ -670,8 +670,10 @@ step-mksnapshot-build: &step-mksnapshot-build
if [ "`uname`" != "Darwin" ]; then
if [ "$TARGET_ARCH" == "arm" ]; then
electron/script/strip-binaries.py --file $PWD/out/Default/clang_x86_v8_arm/mksnapshot
electron/script/strip-binaries.py --file $PWD/out/Default/clang_x86_v8_arm/v8_context_snapshot_generator
elif [ "$TARGET_ARCH" == "arm64" ]; then
electron/script/strip-binaries.py --file $PWD/out/Default/clang_x64_v8_arm64/mksnapshot
electron/script/strip-binaries.py --file $PWD/out/Default/clang_x64_v8_arm64/v8_context_snapshot_generator
else
electron/script/strip-binaries.py --file $PWD/out/Default/mksnapshot
electron/script/strip-binaries.py --file $PWD/out/Default/v8_context_snapshot_generator
@@ -1162,8 +1164,8 @@ steps-tests: &steps-tests
ELECTRON_DISABLE_SECURITY_WARNINGS: 1
command: |
cd src
(cd electron && node script/yarn test --runners=main --enable-logging --files $(circleci tests glob spec-main/*-spec.ts | circleci tests split))
(cd electron && node script/yarn test --runners=remote --enable-logging --files $(circleci tests glob spec/*-spec.js | circleci tests split))
(cd electron && node script/yarn test --runners=main --trace-uncaught --enable-logging --files $(circleci tests glob spec-main/*-spec.ts | circleci tests split))
(cd electron && node script/yarn test --runners=remote --trace-uncaught --enable-logging --files $(circleci tests glob spec/*-spec.js | circleci tests split))
- run:
name: Check test results existence
command: |

View File

@@ -27,7 +27,11 @@
"sourceType": "module"
},
"globals": {
"standardScheme": "readonly"
"standardScheme": "readonly",
"BUILDFLAG": "readonly",
"ENABLE_DESKTOP_CAPTURER": "readonly",
"ENABLE_REMOTE_MODULE": "readonly",
"ENABLE_VIEWS_API": "readonly"
},
"overrides": [
{

View File

@@ -15,6 +15,7 @@ Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTIN
- [ ] relevant documentation is changed or added
- [ ] PR title follows semantic [commit guidelines](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines)
- [ ] [PR release notes](https://github.com/electron/clerk/blob/master/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/master/README.md#examples).
- [ ] This is **NOT A BREAKING CHANGE**. Breaking changes may not be merged to master until 11-x-y is branched.
#### Release Notes

View File

@@ -322,9 +322,11 @@ source_set("electron_lib") {
"shell/common/api:mojo",
"//base:base_static",
"//base/allocator:buildflags",
"//chrome/app:command_ids",
"//chrome/app/resources:platform_locale_settings",
"//chrome/services/printing/public/mojom",
"//components/certificate_transparency",
"//components/crash/core/app",
"//components/language/core/browser",
"//components/net_log",
"//components/network_hints/browser",
@@ -333,6 +335,7 @@ source_set("electron_lib") {
"//components/network_session_configurator/common",
"//components/pref_registry",
"//components/prefs",
"//components/upload_list",
"//components/user_prefs",
"//components/viz/host",
"//components/viz/service",
@@ -362,6 +365,7 @@ source_set("electron_lib") {
"//third_party/blink/public:blink",
"//third_party/boringssl",
"//third_party/electron_node:node_lib",
"//third_party/inspector_protocol:crdtp",
"//third_party/leveldatabase",
"//third_party/libyuv",
"//third_party/webrtc_overrides:webrtc_component",
@@ -446,10 +450,15 @@ source_set("electron_lib") {
]
}
if (is_linux) {
deps += [ "//components/crash/content/browser" ]
}
if (is_mac) {
deps += [
"//components/remote_cocoa/app_shim",
"//content/common:mac_helpers",
"//third_party/crashpad/crashpad/client",
"//ui/accelerated_widget_mac",
]
@@ -471,11 +480,7 @@ source_set("electron_lib") {
]
if (is_mas_build) {
sources += [ "shell/browser/api/electron_api_app_mas.mm" ]
sources -= [
"shell/browser/auto_updater_mac.mm",
"shell/common/crash_reporter/crash_reporter_mac.h",
"shell/common/crash_reporter/crash_reporter_mac.mm",
]
sources -= [ "shell/browser/auto_updater_mac.mm" ]
defines += [ "MAS_BUILD" ]
} else {
libs += [
@@ -498,7 +503,6 @@ source_set("electron_lib") {
"//build/config/linux/gtk",
"//dbus",
"//device/bluetooth",
"//third_party/breakpad:client",
"//ui/events/devices/x11",
"//ui/events/platform/x11",
"//ui/gtk",
@@ -512,7 +516,6 @@ source_set("electron_lib") {
]
}
configs += [ ":gio_unix" ]
include_dirs += [ "//third_party/breakpad" ]
configs += [ "//build/config/linux:x11" ]
defines += [
# Disable warnings for g_settings_list_schemas.
@@ -521,6 +524,16 @@ source_set("electron_lib") {
sources += filenames.lib_sources_nss
sources += [
"shell/browser/ui/gtk/app_indicator_icon.cc",
"shell/browser/ui/gtk/app_indicator_icon.h",
"shell/browser/ui/gtk/app_indicator_icon_menu.cc",
"shell/browser/ui/gtk/app_indicator_icon_menu.h",
"shell/browser/ui/gtk/gtk_status_icon.cc",
"shell/browser/ui/gtk/gtk_status_icon.h",
"shell/browser/ui/gtk/menu_util.cc",
"shell/browser/ui/gtk/menu_util.h",
"shell/browser/ui/gtk/status_icon.cc",
"shell/browser/ui/gtk/status_icon.h",
"shell/browser/ui/gtk_util.cc",
"shell/browser/ui/gtk_util.h",
]
@@ -528,6 +541,7 @@ source_set("electron_lib") {
if (is_win) {
libs += [ "dwmapi.lib" ]
deps += [
"//components/crash/core/app:crash_export_thunks",
"//ui/native_theme:native_theme_browser",
"//ui/views/controls/webview",
"//ui/wm",
@@ -539,14 +553,6 @@ source_set("electron_lib") {
]
}
if ((is_mac && !is_mas_build) || is_win) {
sources += [
"shell/common/crash_reporter/crash_reporter_crashpad.cc",
"shell/common/crash_reporter/crash_reporter_crashpad.h",
]
deps += [ "//third_party/crashpad/crashpad/client" ]
}
if (enable_plugins) {
deps += [ "chromium_src:plugins" ]
sources += [
@@ -586,8 +592,6 @@ source_set("electron_lib") {
if (enable_remote_module) {
sources += [
"shell/common/api/remote/object_life_monitor.cc",
"shell/common/api/remote/object_life_monitor.h",
"shell/common/api/remote/remote_callback_freer.cc",
"shell/common/api/remote/remote_callback_freer.h",
"shell/common/api/remote/remote_object_freer.cc",
@@ -751,11 +755,11 @@ if (is_mac) {
}
bundle_data("electron_crashpad_helper") {
sources = [ "$root_out_dir/crashpad_handler" ]
sources = [ "$root_out_dir/chrome_crashpad_handler" ]
outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
outputs = [ "{{bundle_contents_dir}}/Helpers/{{source_file_part}}" ]
public_deps = [ "//third_party/crashpad/crashpad/handler:crashpad_handler" ]
public_deps = [ "//components/crash/core/app:chrome_crashpad_handler" ]
if (is_asan) {
# crashpad_handler requires the ASan runtime at its @executable_path.
@@ -770,6 +774,7 @@ if (is_mac) {
framework_contents = [
"Resources",
"Libraries",
"Helpers",
]
public_deps = [
":electron_framework_libraries",
@@ -993,10 +998,10 @@ if (is_mac) {
}
extract_symbols("crashpad_handler_syms") {
binary = "$root_out_dir/crashpad_handler"
binary = "$root_out_dir/chrome_crashpad_handler"
symbol_dir = "$root_out_dir/breakpad_symbols"
dsym_file = "$root_out_dir/crashpad_handler.dSYM/Contents/Resources/DWARF/crashpad_handler"
deps = [ "//third_party/crashpad/crashpad/handler:crashpad_handler" ]
dsym_file = "$root_out_dir/chrome_crashpad_handler.dSYM/Contents/Resources/DWARF/chrome_crashpad_handler"
deps = [ "//components/crash/core/app:chrome_crashpad_handler" ]
}
group("electron_symbols") {
@@ -1037,6 +1042,7 @@ if (is_mac) {
":electron_app_manifest",
":electron_lib",
":packed_resources",
"//components/crash/core/app",
"//content:sandbox_helper_win",
"//electron/buildflags",
"//ui/strings",
@@ -1066,6 +1072,11 @@ if (is_mac) {
"shell/browser/resources/win/resource.h",
]
deps += [
"//components/browser_watcher:browser_watcher_client",
"//components/crash/core/app:run_as_crashpad_handler",
]
libs = [
"comctl32.lib",
"uiautomationcore.lib",
@@ -1269,7 +1280,7 @@ dist_zip("electron_chromedriver_zip") {
mksnapshot_deps = [
":licenses",
"//tools/v8_context_snapshot:v8_context_snapshot_generator",
"//tools/v8_context_snapshot:v8_context_snapshot_generator($v8_snapshot_toolchain)",
"//v8:mksnapshot($v8_snapshot_toolchain)",
]

4
DEPS
View File

@@ -5,6 +5,7 @@ gclient_gn_args = [
'checkout_android_native_support',
'checkout_libaom',
'checkout_nacl',
'checkout_pgo_profiles',
'checkout_oculus_sdk',
'checkout_openxr',
'checkout_google_benchmark'
@@ -12,7 +13,7 @@ gclient_gn_args = [
vars = {
'chromium_version':
'17da1064b910f4170320ff37e971064916aed1dc',
'ff6c4f4b826d66c2e32380bf5d1eb5e1fe37faef',
'node_version':
'v12.16.3',
'nan_version':
@@ -42,6 +43,7 @@ vars = {
'checkout_chromium': True,
'checkout_node': True,
'checkout_nan': True,
'checkout_pgo_profiles': True,
# It's only needed to parse the native tests configurations.
'checkout_pyyaml': False,

View File

@@ -1 +1 @@
10.0.0-nightly.20200505
11.0.0-nightly.20200604

View File

@@ -152,7 +152,11 @@ build_script:
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
- ninja -C out/Default electron:electron_dist_zip
- ninja -C out/Default shell_browser_ui_unittests
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
- ninja -C out/Default electron:electron_mksnapshot_zip
- cd out\Default
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
- cd ..\..
- ninja -C out/Default electron:hunspell_dictionaries_zip
- ninja -C out/Default electron:electron_chromedriver_zip
- ninja -C out/Default third_party/electron_node:headers
@@ -200,11 +204,10 @@ test_script:
echo "Skipping tests for $env:GN_CONFIG build"
}
- cd electron
- if "%RUN_TESTS%"=="true" ( echo Running test suite & node script/yarn test -- --enable-logging)
- if "%RUN_TESTS%"=="true" ( echo Running test suite & node script/yarn test -- --trace-uncaught --enable-logging)
- cd ..
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
- echo "About to verify mksnapshot"
- if "%RUN_TESTS%"=="true" ( gn desc out\Default v8:run_mksnapshot_default args > out\Default\mksnapshot_args )
- echo "About to verify mksnapshot"
- if "%RUN_TESTS%"=="true" ( echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd% )
- echo "Done verifying mksnapshot"
- if "%RUN_TESTS%"=="true" ( echo Verifying chromedriver & python electron\script\verify-chromedriver.py --build-dir out\Default --source-root %cd% )

View File

@@ -1,3 +1,4 @@
const fs = require('fs');
const path = require('path')
const webpack = require('webpack')
@@ -9,6 +10,9 @@ config.output = {
filename: path.basename(outPath)
}
const { wrapInitWithProfilingTimeout } = config;
delete config.wrapInitWithProfilingTimeout;
webpack(config, (err, stats) => {
if (err) {
console.error(err)
@@ -17,6 +21,18 @@ webpack(config, (err, stats) => {
console.error(stats.toString('normal'))
process.exit(1)
} else {
if (wrapInitWithProfilingTimeout) {
const contents = fs.readFileSync(outPath, 'utf8');
const newContents = `function ___electron_webpack_init__() {
${contents}
};
if ((globalThis.process || binding.process).argv.includes("--profile-electron-init")) {
setTimeout(___electron_webpack_init__, 0);
} else {
___electron_webpack_init__();
}`;
fs.writeFileSync(outPath, newContents);
}
process.exit(0)
}
})

View File

@@ -20,11 +20,55 @@ class AccessDependenciesPlugin {
}
}
const defines = {
BUILDFLAG: onlyPrintingGraph ? '(a => a)' : ''
}
const buildFlagsPrefix = '--buildflags='
const buildFlagArg = process.argv.find(arg => arg.startsWith(buildFlagsPrefix));
if (buildFlagArg) {
const buildFlagPath = buildFlagArg.substr(buildFlagsPrefix.length)
const flagFile = fs.readFileSync(buildFlagPath, 'utf8')
for (const line of flagFile.split(/(\r\n|\r|\n)/g)) {
const flagMatch = line.match(/#define BUILDFLAG_INTERNAL_(.+?)\(\) \(([01])\)/)
if (flagMatch) {
const [, flagName, flagValue] = flagMatch;
defines[flagName] = JSON.stringify(Boolean(parseInt(flagValue, 10)));
}
}
}
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_REMOTE_MODULE'] === 'false') {
ignoredModules.push(
'@electron/internal/browser/remote/server',
'@electron/internal/renderer/api/remote'
)
}
if (defines['ENABLE_VIEWS_API'] === 'false') {
ignoredModules.push(
'@electron/internal/browser/api/views/image-view.js'
)
}
module.exports = ({
alwaysHasNode,
loadElectronFromAlternateTarget,
targetDeletesNodeGlobals,
target
target,
wrapInitWithProfilingTimeout
}) => {
let entry = path.resolve(electronRoot, 'lib', target, 'init.ts')
if (!fs.existsSync(entry)) {
@@ -39,23 +83,30 @@ module.exports = ({
output: {
filename: `${target}.bundle.js`
},
wrapInitWithProfilingTimeout,
resolve: {
alias: {
'@electron/internal': path.resolve(electronRoot, 'lib'),
'electron': path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.ts'),
// Force timers to resolve to our dependency that doens't use window.postMessage
// Force timers to resolve to our dependency that doesn't use window.postMessage
'timers': path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
},
extensions: ['.ts', '.js']
},
module: {
rules: [{
test: (moduleName) => !onlyPrintingGraph && ignoredModules.includes(moduleName),
loader: 'null-loader',
}, {
test: /\.ts$/,
loader: 'ts-loader',
options: {
configFile: path.resolve(electronRoot, 'tsconfig.electron.json'),
transpileOnly: onlyPrintingGraph,
ignoreDiagnostics: [6059]
ignoreDiagnostics: [
// File '{0}' is not under 'rootDir' '{1}'.
6059,
]
}
}]
},
@@ -78,6 +129,7 @@ module.exports = ({
new webpack.ProvidePlugin({
Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise'],
}),
new webpack.DefinePlugin(defines),
]
})
}

View File

@@ -1,5 +1,6 @@
module.exports = require('./webpack.config.base')({
target: 'renderer',
alwaysHasNode: true,
targetDeletesNodeGlobals: true
targetDeletesNodeGlobals: true,
wrapInitWithProfilingTimeout: true
})

View File

@@ -1,4 +1,5 @@
module.exports = require('./webpack.config.base')({
target: 'sandboxed_renderer',
alwaysHasNode: false
alwaysHasNode: false,
wrapInitWithProfilingTimeout: true,
})

View File

@@ -16,6 +16,7 @@ template("webpack_build") {
inputs = [
invoker.config_file,
"//electron/build/webpack/webpack.config.base.js",
"//electron/build/webpack/run-compiler.js",
"//electron/tsconfig.json",
"//electron/yarn.lock",
"//electron/typings/internal-ambient.d.ts",
@@ -25,7 +26,9 @@ template("webpack_build") {
args = [
rebase_path(invoker.config_file),
rebase_path(invoker.out_file),
"--buildflags=" + rebase_path("$target_gen_dir/buildflags/buildflags.h"),
]
deps += [ "buildflags" ]
outputs = [ invoker.out_file ]
}

View File

@@ -25,6 +25,13 @@ PATHS_TO_SKIP = [
# //chrome/browser/resources/ssl/ssl_error_assistant, but we don't need to
# ship it.
'pyproto',
# On Windows, this binary doesn't exist (the crashpad handler is built-in).
# On MacOS, the binary is called 'chrome_crashpad_handler' and is inside the
# app bundle.
# On Linux, we don't use crashpad, but this binary is still built for some
# reason. Exclude it from the zip.
'./crashpad_handler',
]
def skip_path(dep, dist_zip, target_cpu):

View File

@@ -14,6 +14,8 @@ static_library("chrome") {
sources = [
"//chrome/browser/browser_process.cc",
"//chrome/browser/browser_process.h",
"//chrome/browser/crash_upload_list/crash_upload_list_crashpad.cc",
"//chrome/browser/crash_upload_list/crash_upload_list_crashpad.h",
"//chrome/browser/devtools/devtools_contents_resizing_strategy.cc",
"//chrome/browser/devtools/devtools_contents_resizing_strategy.h",
"//chrome/browser/devtools/devtools_embedder_message_dispatcher.cc",
@@ -55,6 +57,8 @@ static_library("chrome") {
"//chrome/browser/ui/views/autofill/autofill_popup_view_utils.h",
"//chrome/browser/win/chrome_process_finder.cc",
"//chrome/browser/win/chrome_process_finder.h",
"//chrome/child/v8_crashpad_support_win.cc",
"//chrome/child/v8_crashpad_support_win.h",
"//extensions/browser/app_window/size_constraints.cc",
"//extensions/browser/app_window/size_constraints.h",
]
@@ -68,6 +72,7 @@ static_library("chrome") {
]
deps = [
"//chrome/browser:resource_prefetch_predictor_proto",
"//chrome/services/speech:buildflags",
"//components/feature_engagement:buildflags",
"//components/optimization_guide/proto:optimization_guide_proto",
]

View File

@@ -92,7 +92,6 @@ These individual tutorials expand on topics discussed in the guide above.
* Electron Releases & Developer Feedback
* [Versioning Policy](tutorial/electron-versioning.md)
* [Release Timelines](tutorial/electron-timelines.md)
* [App Feedback Program](tutorial/app-feedback-program.md)
* [Packaging App Source Code with asar](tutorial/application-packaging.md)
* [Generating asar Archives](tutorial/application-packaging.md#generating-asar-archives)
* [Using asar Archives](tutorial/application-packaging.md#using-asar-archives)

View File

@@ -369,6 +369,30 @@ Returns:
Emitted when the renderer process of `webContents` crashes or is killed.
**Deprecated:** This event is superceded by the `render-process-gone` event
which contains more information about why the render process dissapeared. It
isn't always because it crashed. The `killed` boolean can be replaced by
checking `reason === 'killed'` when you switch to that event.
#### Event: 'render-process-gone'
Returns:
* `event` Event
* `webContents` [WebContents](web-contents.md)
* `details` Object
* `reason` String - The reason the render process is gone. Possible values:
* `clean-exit` - Process exited with an exit code of zero
* `abnormal-exit` - Process exited with a non-zero exit code
* `killed` - Process was sent a SIGTERM or otherwise killed externally
* `crashed` - Process crashed
* `oom` - Process ran out of memory
* `launch-failure` - Process never successfully launched
* `integrity-failure` - Windows code integrity checks failed
Emitted when the renderer process unexpectedly dissapears. This is normally
because it was crashed or killed.
### Event: 'accessibility-support-changed' _macOS_ _Windows_
Returns:
@@ -608,8 +632,10 @@ Returns `String` - The current application directory.
* `music` Directory for a user's music.
* `pictures` Directory for a user's pictures.
* `videos` Directory for a user's videos.
* `recent` Directory for the user's recent files (Windows only).
* `logs` Directory for your app's log folder.
* `pepperFlashSystemPlugin` Full path to the system version of the Pepper Flash plugin.
* `crashDumps` Directory where crash dumps are stored.
Returns `String` - A path to a special directory or file associated with `name`. On
failure, an `Error` is thrown.
@@ -1278,6 +1304,25 @@ app.moveToApplicationsFolder({
Would mean that if an app already exists in the user directory, if the user chooses to 'Continue Move' then the function would continue with its default behavior and the existing app will be trashed and the active app moved into its place.
### `app.isSecureKeyboardEntryEnabled()` _macOS_
Returns `Boolean` - whether `Secure Keyboard Entry` is enabled.
By default this API will return `false`.
### `app.setSecureKeyboardEntryEnabled(enabled)` _macOS_
* `enabled` Boolean - Enable or disable `Secure Keyboard Entry`
Set the `Secure Keyboard Entry` is enabled in your application.
By using this API, important information such as password and other sensitive information can be prevented from being intercepted by other processes.
See [Apple's documentation](https://developer.apple.com/library/archive/technotes/tn2150/_index.html) for more
details.
**Note:** Enable `Secure Keyboard Entry` only when it is needed and disable it when it is no longer needed.
## Properties
### `app.accessibilitySupportEnabled` _macOS_ _Windows_
@@ -1304,6 +1349,9 @@ On macOS, setting this with any nonzero integer shows on the dock icon. On Linux
**Note:** Unity launcher requires the existence of a `.desktop` file to work,
for more information please read [Desktop Environment Integration][unity-requirement].
**Note:** On macOS, you need to ensure that your application has the permission
to display notifications for this property to take effect.
### `app.commandLine` _Readonly_
A [`CommandLine`](./command-line.md) object that allows you to read and manipulate the
@@ -1355,7 +1403,7 @@ in your app's initialization to ensure that your overridden value is used.
A `Boolean` which when `true` disables the overrides that Electron has in place
to ensure renderer processes are restarted on every navigation. The current
default value for this property is `false`.
default value for this property is `true`.
The intention is for these overrides to become disabled by default and then at
some point in the future this property will be removed. This property impacts

View File

@@ -385,6 +385,15 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
visible to users.
* `spellcheck` Boolean (optional) - Whether to enable the builtin spellchecker.
Default is `true`.
* `enableWebSQL` Boolean (optional) - Whether to enable the [WebSQL api](https://www.w3.org/TR/webdatabase/).
Default is `true`.
* `v8CacheOptions` String (optional) - Enforces the v8 code caching policy
used by blink. Accepted values are
* `none` - Disables code caching
* `code` - Heuristic based code caching
* `bypassHeatCheck` - Bypass code caching heuristics but with lazy compilation
* `bypassHeatCheckAndEagerCompile` - Same as above except compilation is eager.
Default policy is `code`.
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from

View File

@@ -36,6 +36,10 @@ for integrated authentication. Without `*` prefix the URL has to match exactly.
A comma-separated list of servers for which delegation of user credentials is required.
Without `*` prefix the URL has to match exactly.
### --disable-ntlm-v2
Disables NTLM v2 for posix platforms, no effect elsewhere.
### --disable-http-cache
Disables the disk cache for HTTP requests.

View File

@@ -4,18 +4,13 @@
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process)
The following is an example of automatically submitting a crash report to a
remote server:
The following is an example of setting up Electron to automatically submit
crash reports to a remote server:
```javascript
const { crashReporter } = require('electron')
crashReporter.start({
productName: 'YourName',
companyName: 'YourCompany',
submitURL: 'https://your-domain.com/url-to-submit',
uploadToServer: true
})
crashReporter.start({ submitURL: 'https://your-domain.com/url-to-submit' })
```
For setting up a server to accept and process crash reports, you can use
@@ -30,11 +25,19 @@ Or use a 3rd party hosted solution:
* [Sentry](https://docs.sentry.io/clients/electron)
* [BugSplat](https://www.bugsplat.com/docs/platforms/electron)
Crash reports are saved locally in an application-specific temp directory folder.
For a `productName` of `YourName`, crash reports will be stored in a folder
named `YourName Crashes` inside the temp directory. You can customize this temp
directory location for your app by calling the `app.setPath('temp', '/my/custom/temp')`
API before starting the crash reporter.
Crash reports are stored temporarily before being uploaded in a directory
underneath the app's user data directory (called 'Crashpad' on Windows and Mac,
or 'Crash Reports' on Linux). You can override this directory by calling
`app.setPath('crashDumps', '/path/to/crashes')` before starting the crash
reporter.
On Windows and macOS, Electron uses
[crashpad](https://chromium.googlesource.com/crashpad/crashpad/+/master/README.md)
to monitor and report crashes. On Linux, Electron uses
[breakpad](https://chromium.googlesource.com/breakpad/breakpad/+/master/). This
is an implementation detail driven by Chromium, and it may change in future. In
particular, crashpad is newer and will likely eventually replace breakpad on
all platforms.
## Methods
@@ -43,45 +46,67 @@ The `crashReporter` module has the following methods:
### `crashReporter.start(options)`
* `options` Object
* `companyName` String
* `submitURL` String - URL that crash reports will be sent to as POST.
* `productName` String (optional) - Defaults to `app.name`.
* `uploadToServer` Boolean (optional) - Whether crash reports should be sent to the server. Default is `true`.
* `ignoreSystemCrashHandler` Boolean (optional) - Default is `false`.
* `companyName` String (optional) _Deprecated_ - Deprecated alias for
`{ globalExtra: { _companyName: ... } }`.
* `uploadToServer` Boolean (optional) - Whether crash reports should be sent
to the server. If false, crash reports will be collected and stored in the
crashes directory, but not uploaded. Default is `true`.
* `ignoreSystemCrashHandler` Boolean (optional) - If true, crashes generated
in the main process will not be forwarded to the system crash handler.
Default is `false`.
* `rateLimit` Boolean (optional) _macOS_ _Windows_ - If true, limit the
number of crashes uploaded to 1/hour. Default is `false`.
* `compress` Boolean (optional) _macOS_ _Windows_ - If true, crash reports
will be compressed and uploaded with `Content-Encoding: gzip`. Not all
collection servers support compressed payloads. Default is `false`.
* `extra` Record<String, String> (optional) - An object you can define that will be sent along with the
report. Only string properties are sent correctly. Nested objects are not
supported. When using Windows, the property names and values must be fewer than 64 characters.
* `crashesDirectory` String (optional) - Directory to store the crash reports temporarily (only used when the crash reporter is started via `process.crashReporter.start`).
* `compress` Boolean (optional) - If true, crash reports will be compressed
and uploaded with `Content-Encoding: gzip`. Default is `false`.
* `extra` Record<String, String> (optional) - Extra string key/value
annotations that will be sent along with crash reports that are generated
in the main process. Only string values are supported. Crashes generated in
child processes will not contain these extra
parameters to crash reports generated from child processes, call
[`addExtraParameter`](#crashreporteraddextraparameterkey-value) from the
child process.
* `globalExtra` Record<String, String> (optional) - Extra string key/value
annotations that will be sent along with any crash reports generated in any
process. These annotations cannot be changed once the crash reporter has
been started. If a key is present in both the global extra parameters and
the process-specific extra parameters, then the global one will take
precedence. By default, `productName` and the app version are included, as
well as the Electron version.
You are required to call this method before using any other `crashReporter` APIs
and in each process (main/renderer) from which you want to collect crash reports.
You can pass different options to `crashReporter.start` when calling from different processes.
This method must be called before using any other `crashReporter` APIs. Once
initialized this way, the crashpad handler collects crashes from all
subsequently created processes. The crash reporter cannot be disabled once
started.
**Note** Child processes created via the `child_process` module will not have access to the Electron modules.
Therefore, to collect crash reports from them, use `process.crashReporter.start` instead. Pass the same options as above
along with an additional one called `crashesDirectory` that should point to a directory to store the crash
reports temporarily. You can test this out by calling `process.crash()` to crash the child process.
This method should be called as early as possible in app startup, preferably
before `app.on('ready')`. If the crash reporter is not initialized at the time
a renderer process is created, then that renderer process will not be monitored
by the crash reporter.
**Note:** If you need send additional/updated `extra` parameters after your
first call `start` you can call `addExtraParameter` on macOS or call `start`
again with the new/updated `extra` parameters on Linux and Windows.
**Note:** You can test out the crash reporter by generating a crash using
`process.crash()`.
**Note:** On macOS and windows, Electron uses a new `crashpad` client for crash collection and reporting.
If you want to enable crash reporting, initializing `crashpad` from the main process using `crashReporter.start` is required
regardless of which process you want to collect crashes from. Once initialized this way, the crashpad handler collects
crashes from all processes. You still have to call `crashReporter.start` from the renderer or child process, otherwise crashes from
them will get reported without `companyName`, `productName` or any of the `extra` information.
**Note:** If you need to send additional/updated `extra` parameters after your
first call `start` you can call `addExtraParameter`.
**Note:** Parameters passed in `extra`, `globalExtra` or set with
`addExtraParameter` have limits on the length of the keys and values. Key names
must be at most 39 bytes long, and values must be no longer than 127 bytes.
Keys with names longer than the maximum will be silently ignored. Key values
longer than the maximum length will be truncated.
**Note:** Calling this method from the renderer process is deprecated.
### `crashReporter.getLastCrashReport()`
Returns [`CrashReport`](structures/crash-report.md):
Returns [`CrashReport`](structures/crash-report.md) - The date and ID of the
last crash report. Only crash reports that have been uploaded will be returned;
even if a crash report is present on disk it will not be returned until it is
uploaded. In the case that there are no uploaded reports, `null` is returned.
Returns the date and ID of the last crash report. Only crash reports that have been uploaded will be returned; even if a crash report is present on disk it will not be returned until it is uploaded. In the case that there are no uploaded reports, `null` is returned.
**Note:** Calling this method from the renderer process is deprecated.
### `crashReporter.getUploadedReports()`
@@ -90,43 +115,61 @@ Returns [`CrashReport[]`](structures/crash-report.md):
Returns all uploaded crash reports. Each report contains the date and uploaded
ID.
**Note:** Calling this method from the renderer process is deprecated.
### `crashReporter.getUploadToServer()`
Returns `Boolean` - Whether reports should be submitted to the server. Set through
the `start` method or `setUploadToServer`.
**Note:** This API can only be called from the main process.
**Note:** Calling this method from the renderer process is deprecated.
### `crashReporter.setUploadToServer(uploadToServer)`
* `uploadToServer` Boolean _macOS_ - Whether reports should be submitted to the server.
* `uploadToServer` Boolean - Whether reports should be submitted to the server.
This would normally be controlled by user preferences. This has no effect if
called before `start` is called.
**Note:** This API can only be called from the main process.
**Note:** Calling this method from the renderer process is deprecated.
### `crashReporter.addExtraParameter(key, value)` _macOS_ _Windows_
### `crashReporter.getCrashesDirectory()` _Deprecated_
* `key` String - Parameter key, must be less than 64 characters long.
* `value` String - Parameter value, must be less than 64 characters long.
Returns `String` - The directory where crashes are temporarily stored before being uploaded.
Set an extra parameter to be sent with the crash report. The values
specified here will be sent in addition to any values set via the `extra` option when `start` was called. This API is only available on macOS and windows, if you need to add/update extra parameters on Linux after your first call to `start` you can call `start` again with the updated `extra` options.
**Note:** This method is deprecated, use `app.getPath('crashDumps')` instead.
### `crashReporter.removeExtraParameter(key)` _macOS_ _Windows_
### `crashReporter.addExtraParameter(key, value)`
* `key` String - Parameter key, must be less than 64 characters long.
* `key` String - Parameter key, must be no longer than 39 bytes.
* `value` String - Parameter value, must be no longer than 127 bytes.
Remove a extra parameter from the current set of parameters so that it will not be sent with the crash report.
Set an extra parameter to be sent with the crash report. The values specified
here will be sent in addition to any values set via the `extra` option when
`start` was called.
Parameters added in this fashion (or via the `extra` parameter to
`crashReporter.start`) are specific to the calling process. Adding extra
parameters in the main process will not cause those parameters to be sent along
with crashes from renderer or other child processes. Similarly, adding extra
parameters in a renderer process will not result in those parameters being sent
with crashes that occur in other renderer processes or in the main process.
**Note:** Parameters have limits on the length of the keys and values. Key
names must be no longer than 39 bytes, and values must be no longer than 127
bytes. Keys with names longer than the maximum will be silently ignored. Key
values longer than the maximum length will be truncated.
### `crashReporter.removeExtraParameter(key)`
* `key` String - Parameter key, must be no longer than 39 bytes.
Remove a extra parameter from the current set of parameters. Future crashes
will not include this parameter.
### `crashReporter.getParameters()`
See all of the current parameters being passed to the crash reporter.
### `crashReporter.getCrashesDirectory()`
Returns `String` - The directory where crashes are temporarily stored before being uploaded.
Returns `Record<String, String>` - The current 'extra' parameters of the crash reporter.
## Crash Report Payload

View File

@@ -3,7 +3,7 @@
> Access information about media sources that can be used to capture audio and
> video from the desktop using the [`navigator.mediaDevices.getUserMedia`] API.
Process: [Renderer](../glossary.md#renderer-process)
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process)
The following example shows how to capture video from a desktop window whose
title is `Electron`:
@@ -72,6 +72,50 @@ const constraints = {
}
```
This example shows how to capture a video from a [WebContents](web-contents.md)
```javascript
// In the renderer process.
const { desktopCapturer, remote } = require('electron')
desktopCapturer.getMediaSourceIdForWebContents(remote.getCurrentWebContents().id).then(async mediaSourceId => {
try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: {
mandatory: {
chromeMediaSource: 'tab',
chromeMediaSourceId: mediaSourceId
}
},
video: {
mandatory: {
chromeMediaSource: 'tab',
chromeMediaSourceId: mediaSourceId,
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720
}
}
})
handleStream(stream)
} catch (e) {
handleError(e)
}
})
function handleStream (stream) {
const video = document.querySelector('video')
video.srcObject = stream
video.onloadedmetadata = (e) => video.play()
}
function handleError (e) {
console.log(e)
}
```
## Methods
The `desktopCapturer` module has the following methods:
@@ -94,6 +138,15 @@ Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`Desktop
**Note** Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher,
which can detected by [`systemPreferences.getMediaAccessStatus`].
### `desktopCapturer.getMediaSourceIdForWebContents(webContentsId)`
* `webContentsId` number - Id of the WebContents to get stream of
Returns `Promise<string>` - Resolves with the identifier of a WebContents stream, this identifier can be
used with [`navigator.mediaDevices.getUserMedia`].
The identifier is **only valid for 10 seconds**.
The identifier may be empty if not requested from a renderer process.
[`navigator.mediaDevices.getUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/MediaDevices/getUserMedia
[`systemPreferences.getMediaAccessStatus`]: system-preferences.md#systempreferencesgetmediaaccessstatusmediatype-macos

View File

@@ -147,3 +147,14 @@ the one downloaded by `npm install`. Usage:
```sh
export ELECTRON_OVERRIDE_DIST_PATH=/Users/username/projects/electron/out/Testing
```
## Set By Electron
Electron sets some variables in your environment at runtime.
### `ORIGINAL_XDG_CURRENT_DESKTOP`
This variable is set to the value of `XDG_CURRENT_DESKTOP` that your application
originally launched with. Electron sometimes modifies the value of `XDG_CURRENT_DESKTOP`
to affect other logic within Chromium so if you want access to the _original_ value
you should look up this environment variable instead.

View File

@@ -69,6 +69,7 @@ a `type`.
The `role` property can have following values:
* `undo`
* `about` - Trigger a native about panel (custom message box on Window, which does not provide its own).
* `redo`
* `cut`
* `copy`
@@ -94,7 +95,6 @@ The `role` property can have following values:
The following additional roles are available on _macOS_:
* `appMenu` - Whole default "App" menu (About, Services, etc.)
* `about` - Map to the `orderFrontStandardAboutPanel` action.
* `hide` - Map to the `hide` action.
* `hideOthers` - Map to the `hideOtherApplications` action.
* `unhide` - Map to the `unhideAllApplications` action.

View File

@@ -34,6 +34,7 @@ The Electron team is currently undergoing an initiative to convert separate gett
* `fullscreenable`
* `movable`
* `closable`
* `backgroundThrottling`
* `NativeImage`
* `isMacTemplateImage`
* `SystemPreferences` module

View File

@@ -266,9 +266,13 @@ image instead of a copy, so you _must_ ensure that the associated
Returns `Boolean` - Whether the image is empty.
#### `image.getSize()`
#### `image.getSize([scaleFactor])`
Returns [`Size`](structures/size.md)
* `scaleFactor` Double (optional) - Defaults to 1.0.
Returns [`Size`](structures/size.md).
If `scaleFactor` is passed, this will return the size corresponding to the image representation most closely matching the passed value.
#### `image.setTemplateImage(option)`
@@ -303,10 +307,18 @@ Returns `NativeImage` - The resized image.
If only the `height` or the `width` are specified then the current aspect ratio
will be preserved in the resized image.
#### `image.getAspectRatio()`
#### `image.getAspectRatio([scaleFactor])`
* `scaleFactor` Double (optional) - Defaults to 1.0.
Returns `Float` - The image's aspect ratio.
If `scaleFactor` is passed, this will return the aspect ratio corresponding to the image representation most closely matching the passed value.
#### `image.getScaleFactors()`
Returns `Float[]` - An array of all scale factors corresponding to representations for a given nativeImage.
#### `image.addRepresentation(options)`
* `options` Object

View File

@@ -1,309 +0,0 @@
# protocol (NetworkService) (Draft)
This document describes the new protocol APIs based on the [NetworkService](https://www.chromium.org/servicification).
We don't currently have an estimate of when we will enable the `NetworkService` by
default in Electron, but as Chromium is already removing non-`NetworkService`
code, we will probably switch before Electron 10.
The content of this document should be moved to `protocol.md` after we have
enabled the `NetworkService` by default in Electron.
> Register a custom protocol and intercept existing protocol requests.
Process: [Main](../glossary.md#main-process)
An example of implementing a protocol that has the same effect as the
`file://` protocol:
```javascript
const { app, protocol } = require('electron')
const path = require('path')
app.whenReady().then(() => {
protocol.registerFileProtocol('atom', (request, callback) => {
const url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
})
})
```
**Note:** All methods unless specified can only be used after the `ready` event
of the `app` module gets emitted.
## Using `protocol` with a custom `partition` or `session`
A protocol is registered to a specific Electron [`session`](./session.md)
object. If you don't specify a session, then your `protocol` will be applied to
the default session that Electron uses. However, if you define a `partition` or
`session` on your `browserWindow`'s `webPreferences`, then that window will use
a different session and your custom protocol will not work if you just use
`electron.protocol.XXX`.
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 path = require('path')
app.whenReady().then(() => {
const partition = 'persist:example'
const ses = session.fromPartition(partition)
ses.protocol.registerFileProtocol('atom', (request, callback) => {
const url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
})
mainWindow = new BrowserWindow({ webPreferences: { partition } })
})
```
## Methods
The `protocol` module has the following methods:
### `protocol.registerSchemesAsPrivileged(customSchemes)`
* `customSchemes` [CustomScheme[]](structures/custom-scheme.md)
**Note:** This method can only be used before the `ready` event of the `app`
module gets emitted and can be called only once.
Registers the `scheme` as standard, secure, bypasses content security policy for
resources, allows registering ServiceWorker and supports fetch API. Specify a
privilege with the value of `true` to enable the capability.
An example of registering a privileged scheme, that bypasses Content Security
Policy:
```javascript
const { protocol } = require('electron')
protocol.registerSchemesAsPrivileged([
{ scheme: 'foo', privileges: { bypassCSP: true } }
])
```
A standard scheme adheres to what RFC 3986 calls [generic URI
syntax](https://tools.ietf.org/html/rfc3986#section-3). For example `http` and
`https` are standard schemes, while `file` is not.
Registering a scheme as standard allows relative and absolute resources to
be resolved correctly when served. Otherwise the scheme will behave like the
`file` protocol, but without the ability to resolve relative URLs.
For example when you load following page with custom protocol without
registering it as standard scheme, the image will not be loaded because
non-standard schemes can not recognize relative URLs:
```html
<body>
<img src='test.png'>
</body>
```
Registering a scheme as standard will allow access to files through the
[FileSystem API][file-system-api]. Otherwise the renderer will throw a security
error for the scheme.
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB,
cookies) are disabled for non standard schemes. So in general if you want to
register a custom protocol to replace the `http` protocol, you have to register
it as a standard scheme.
### `protocol.registerFileProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Registers a protocol of `scheme` that will send a file as the response. The
`handler` will be called with `request` and `callback` where `request` is
an incoming request for the `scheme`.
To handle the `request`, the `callback` should be called with either the file's
path or an object that has a `path` property, e.g. `callback(filePath)` or
`callback({ path: filePath })`. The `filePath` must be an absolute path.
By default the `scheme` is treated like `http:`, which is parsed differently
from protocols that follow the "generic URI syntax" like `file:`.
### `protocol.registerBufferProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
Registers a protocol of `scheme` that will send a `Buffer` as a response.
The usage is the same with `registerFileProtocol`, except that the `callback`
should be called with either a `Buffer` object or an object that has the `data`
property.
Example:
```javascript
protocol.registerBufferProtocol('atom', (request, callback) => {
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
})
```
### `protocol.registerStringProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Registers a protocol of `scheme` that will send a `String` as a response.
The usage is the same with `registerFileProtocol`, except that the `callback`
should be called with either a `String` or an object that has the `data`
property.
### `protocol.registerHttpProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` ProtocolResponse
Registers a protocol of `scheme` that will send an HTTP request as a response.
The usage is the same with `registerFileProtocol`, except that the `callback`
should be called with an object that has the `url` property.
### `protocol.registerStreamProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
Registers a protocol of `scheme` that will send a stream as a response.
The usage is the same with `registerFileProtocol`, except that the
`callback` should be called with either a [`ReadableStream`](https://nodejs.org/api/stream.html#stream_class_stream_readable) object or an object that
has the `data` property.
Example:
```javascript
const { protocol } = require('electron')
const { PassThrough } = require('stream')
function createStream (text) {
const rv = new PassThrough() // PassThrough is also a Readable stream
rv.push(text)
rv.push(null)
return rv
}
protocol.registerStreamProtocol('atom', (request, callback) => {
callback({
statusCode: 200,
headers: {
'content-type': 'text/html'
},
data: createStream('<h5>Response</h5>')
})
})
```
It is possible to pass any object that implements the readable stream API (emits
`data`/`end`/`error` events). For example, here's how a file could be returned:
```javascript
protocol.registerStreamProtocol('atom', (request, callback) => {
callback(fs.createReadStream('index.html'))
})
```
### `protocol.unregisterProtocol(scheme)`
* `scheme` String
Unregisters the custom protocol of `scheme`.
### `protocol.isProtocolRegistered(scheme)`
* `scheme` String
Returns `Boolean` - Whether `scheme` is already registered.
### `protocol.interceptFileProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a file as a response.
### `protocol.interceptStringProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a `String` as a response.
### `protocol.interceptBufferProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a `Buffer` as a response.
### `protocol.interceptHttpProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` ProtocolResponse
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a new HTTP request as a response.
### `protocol.interceptStreamProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
Same as `protocol.registerStreamProtocol`, except that it replaces an existing
protocol handler.
### `protocol.uninterceptProtocol(scheme)`
* `scheme` String
Remove the interceptor installed for `scheme` and restore its original handler.
### `protocol.isProtocolIntercepted(scheme)`
* `scheme` String
Returns `Boolean` - Whether `scheme` is already intercepted.
[file-system-api]: https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem

View File

@@ -15,8 +15,6 @@ app.whenReady().then(() => {
protocol.registerFileProtocol('atom', (request, callback) => {
const url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
}, (error) => {
if (error) console.error('Failed to register protocol')
})
})
```
@@ -26,9 +24,15 @@ of the `app` module gets emitted.
## Using `protocol` with a custom `partition` or `session`
A protocol is registered to a specific Electron [`session`](./session.md) object. If you don't specify a session, then your `protocol` will be applied to the default session that Electron uses. However, if you define a `partition` or `session` on your `browserWindow`'s `webPreferences`, then that window will use a different session and your custom protocol will not work if you just use `electron.protocol.XXX`.
A protocol is registered to a specific Electron [`session`](./session.md)
object. If you don't specify a session, then your `protocol` will be applied to
the default session that Electron uses. However, if you define a `partition` or
`session` on your `browserWindow`'s `webPreferences`, then that window will use
a different session and your custom protocol will not work if you just use
`electron.protocol.XXX`.
To have your custom protocol work in combination with a custom session, you need to register it to that session explicitly.
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')
@@ -41,17 +45,9 @@ app.whenReady().then(() => {
ses.protocol.registerFileProtocol('atom', (request, callback) => {
const url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
}, (error) => {
if (error) console.error('Failed to register protocol')
})
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
partition: partition
}
})
mainWindow = new BrowserWindow({ webPreferences: { partition } })
})
```
@@ -63,15 +59,15 @@ The `protocol` module has the following methods:
* `customSchemes` [CustomScheme[]](structures/custom-scheme.md)
**Note:** This method can only be used before the `ready` event of the `app`
module gets emitted and can be called only once.
Registers the `scheme` as standard, secure, bypasses content security policy for resources,
allows registering ServiceWorker and supports fetch API.
Registers the `scheme` as standard, secure, bypasses content security policy for
resources, allows registering ServiceWorker and supports fetch API. Specify a
privilege with the value of `true` to enable the capability.
Specify a privilege with the value of `true` to enable the capability.
An example of registering a privileged scheme, with bypassing Content Security Policy:
An example of registering a privileged scheme, that bypasses Content Security
Policy:
```javascript
const { protocol } = require('electron')
@@ -84,7 +80,7 @@ A standard scheme adheres to what RFC 3986 calls [generic URI
syntax](https://tools.ietf.org/html/rfc3986#section-3). For example `http` and
`https` are standard schemes, while `file` is not.
Registering a scheme as standard, will allow relative and absolute resources to
Registering a scheme as standard allows relative and absolute resources to
be resolved correctly when served. Otherwise the scheme will behave like the
`file` protocol, but without the ability to resolve relative URLs.
@@ -102,168 +98,102 @@ Registering a scheme as standard will allow access to files through the
[FileSystem API][file-system-api]. Otherwise the renderer will throw a security
error for the scheme.
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB, cookies)
are disabled for non standard schemes. So in general if you want to register a
custom protocol to replace the `http` protocol, you have to register it as a standard scheme.
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB,
cookies) are disabled for non standard schemes. So in general if you want to
register a custom protocol to replace the `http` protocol, you have to register
it as a standard scheme.
`protocol.registerSchemesAsPrivileged` can be used to replicate the functionality of the previous `protocol.registerStandardSchemes`, `webFrame.registerURLSchemeAs*` and `protocol.registerServiceWorkerSchemes` functions that existed prior to Electron 5.0.0, for example:
**before (<= v4.x)**
```javascript
// Main
protocol.registerStandardSchemes(['scheme1', 'scheme2'], { secure: true })
// Renderer
webFrame.registerURLSchemeAsPrivileged('scheme1', { secure: true })
webFrame.registerURLSchemeAsPrivileged('scheme2', { secure: true })
```
**after (>= v5.x)**
```javascript
protocol.registerSchemesAsPrivileged([
{ scheme: 'scheme1', privileges: { standard: true, secure: true } },
{ scheme: 'scheme2', privileges: { standard: true, secure: true } }
])
```
### `protocol.registerFileProtocol(scheme, handler[, completion])`
### `protocol.registerFileProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `request` ProtocolRequest
* `callback` Function
* `filePath` String | [FilePathWithHeaders](structures/file-path-with-headers.md) (optional)
* `completion` Function (optional)
* `error` Error
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Registers a protocol of `scheme` that will send the file as a response. The
`handler` will be called with `handler(request, callback)` when a `request` is
going to be created with `scheme`. `completion` will be called with
`completion(null)` when `scheme` is successfully registered or
`completion(error)` when failed.
Returns `Boolean` - Whether the protocol was successfully registered
Registers a protocol of `scheme` that will send a file as the response. The
`handler` will be called with `request` and `callback` where `request` is
an incoming request for the `scheme`.
To handle the `request`, the `callback` should be called with either the file's
path or an object that has a `path` property, e.g. `callback(filePath)` or
`callback({ path: filePath })`. The object may also have a `headers` property
which gives a map of headers to values for the response headers, e.g.
`callback({ path: filePath, headers: {"Content-Security-Policy": "default-src 'none'"]})`.
When `callback` is called with nothing, a number, or an object that has an
`error` property, the `request` will fail with the `error` number you
specified. For the available error numbers you can use, please see the
[net error list][net-error].
`callback({ path: filePath })`. The `filePath` must be an absolute path.
By default the `scheme` is treated like `http:`, which is parsed differently
than protocols that follow the "generic URI syntax" like `file:`.
from protocols that follow the "generic URI syntax" like `file:`.
### `protocol.registerBufferProtocol(scheme, handler[, completion])`
### `protocol.registerBufferProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `request` ProtocolRequest
* `callback` Function
* `buffer` (Buffer | [MimeTypedBuffer](structures/mime-typed-buffer.md)) (optional)
* `completion` Function (optional)
* `error` Error
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
Returns `Boolean` - Whether the protocol was successfully registered
Registers a protocol of `scheme` that will send a `Buffer` as a response.
The usage is the same with `registerFileProtocol`, except that the `callback`
should be called with either a `Buffer` object or an object that has the `data`,
`mimeType`, and `charset` properties.
should be called with either a `Buffer` object or an object that has the `data`
property.
Example:
```javascript
const { protocol } = require('electron')
protocol.registerBufferProtocol('atom', (request, callback) => {
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
}, (error) => {
if (error) console.error('Failed to register protocol')
})
```
### `protocol.registerStringProtocol(scheme, handler[, completion])`
### `protocol.registerStringProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `request` ProtocolRequest
* `callback` Function
* `data` (String | [StringProtocolResponse](structures/string-protocol-response.md)) (optional)
* `completion` Function (optional)
* `error` Error
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Returns `Boolean` - Whether the protocol was successfully registered
Registers a protocol of `scheme` that will send a `String` as a response.
The usage is the same with `registerFileProtocol`, except that the `callback`
should be called with either a `String` or an object that has the `data`,
`mimeType`, and `charset` properties.
should be called with either a `String` or an object that has the `data`
property.
### `protocol.registerHttpProtocol(scheme, handler[, completion])`
### `protocol.registerHttpProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `request` ProtocolRequest
* `callback` Function
* `redirectRequest` Object
* `url` String
* `method` String (optional)
* `session` Session | null (optional)
* `uploadData` [ProtocolResponseUploadData](structures/protocol-response-upload-data.md) (optional)
* `completion` Function (optional)
* `error` Error
* `response` ProtocolResponse
Returns `Boolean` - Whether the protocol was successfully registered
Registers a protocol of `scheme` that will send an HTTP request as a response.
The usage is the same with `registerFileProtocol`, except that the `callback`
should be called with a `redirectRequest` object that has the `url`, `method`,
`referrer`, `uploadData` and `session` properties.
should be called with an object that has the `url` property.
By default the HTTP request will reuse the current session. If you want the
request to have a different session you should set `session` to `null`.
For POST requests the `uploadData` object must be provided.
### `protocol.registerStreamProtocol(scheme, handler[, completion])`
### `protocol.registerStreamProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `request` ProtocolRequest
* `callback` Function
* `stream` (ReadableStream | [StreamProtocolResponse](structures/stream-protocol-response.md)) (optional)
* `completion` Function (optional)
* `error` Error
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
Registers a protocol of `scheme` that will send a `Readable` as a response.
Returns `Boolean` - Whether the protocol was successfully registered
The usage is similar to the other `register{Any}Protocol`, except that the
`callback` should be called with either a `Readable` object or an object that
has the `data`, `statusCode`, and `headers` properties.
Registers a protocol of `scheme` that will send a stream as a response.
The usage is the same with `registerFileProtocol`, except that the
`callback` should be called with either a [`ReadableStream`](https://nodejs.org/api/stream.html#stream_class_stream_readable) object or an object that
has the `data` property.
Example:
@@ -286,8 +216,6 @@ protocol.registerStreamProtocol('atom', (request, callback) => {
},
data: createStream('<h5>Response</h5>')
})
}, (error) => {
if (error) console.error('Failed to register protocol')
})
```
@@ -295,132 +223,102 @@ It is possible to pass any object that implements the readable stream API (emits
`data`/`end`/`error` events). For example, here's how a file could be returned:
```javascript
const { protocol } = require('electron')
const fs = require('fs')
protocol.registerStreamProtocol('atom', (request, callback) => {
callback(fs.createReadStream('index.html'))
}, (error) => {
if (error) console.error('Failed to register protocol')
})
```
### `protocol.unregisterProtocol(scheme[, completion])`
### `protocol.unregisterProtocol(scheme)`
* `scheme` String
* `completion` Function (optional)
* `error` Error
Returns `Boolean` - Whether the protocol was successfully unregistered
Unregisters the custom protocol of `scheme`.
### `protocol.isProtocolHandled(scheme)`
### `protocol.isProtocolRegistered(scheme)`
* `scheme` String
Returns `Promise<Boolean>` - fulfilled with a boolean that indicates whether there is
already a handler for `scheme`.
Returns `Boolean` - Whether `scheme` is already registered.
### `protocol.interceptFileProtocol(scheme, handler[, completion])`
### `protocol.interceptFileProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `request` ProtocolRequest
* `callback` Function
* `filePath` String
* `completion` Function (optional)
* `error` Error
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Returns `Boolean` - Whether the protocol was successfully intercepted
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a file as a response.
### `protocol.interceptStringProtocol(scheme, handler[, completion])`
### `protocol.interceptStringProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `request` ProtocolRequest
* `callback` Function
* `data` (String | [StringProtocolResponse](structures/string-protocol-response.md)) (optional)
* `completion` Function (optional)
* `error` Error
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Returns `Boolean` - Whether the protocol was successfully intercepted
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a `String` as a response.
### `protocol.interceptBufferProtocol(scheme, handler[, completion])`
### `protocol.interceptBufferProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `request` ProtocolRequest
* `callback` Function
* `buffer` Buffer (optional)
* `completion` Function (optional)
* `error` Error
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
Returns `Boolean` - Whether the protocol was successfully intercepted
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a `Buffer` as a response.
### `protocol.interceptHttpProtocol(scheme, handler[, completion])`
### `protocol.interceptHttpProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `request` ProtocolRequest
* `callback` Function
* `redirectRequest` Object
* `url` String
* `method` String (optional)
* `session` Session | null (optional)
* `uploadData` [ProtocolResponseUploadData](structures/protocol-response-upload-data.md) (optional)
* `completion` Function (optional)
* `error` Error
* `response` [ProtocolResponse](structures/protocol-response.md)
Returns `Boolean` - Whether the protocol was successfully intercepted
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a new HTTP request as a response.
### `protocol.interceptStreamProtocol(scheme, handler[, completion])`
### `protocol.interceptStreamProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `request` ProtocolRequest
* `callback` Function
* `stream` (ReadableStream | [StreamProtocolResponse](structures/stream-protocol-response.md)) (optional)
* `completion` Function (optional)
* `error` Error
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
Returns `Boolean` - Whether the protocol was successfully intercepted
Same as `protocol.registerStreamProtocol`, except that it replaces an existing
protocol handler.
### `protocol.uninterceptProtocol(scheme[, completion])`
### `protocol.uninterceptProtocol(scheme)`
* `scheme` String
* `completion` Function (optional)
* `error` Error
Returns `Boolean` - Whether the protocol was successfully unintercepted
Remove the interceptor installed for `scheme` and restore its original handler.
[net-error]: https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h
### `protocol.isProtocolIntercepted(scheme)`
* `scheme` String
Returns `Boolean` - Whether `scheme` is already intercepted.
[file-system-api]: https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem

View File

@@ -154,24 +154,43 @@ More may be added as needed to expose more Electron APIs in the sandbox, but any
module in the main process can already be used through
`electron.remote.require`.
## Status
## Rendering untrusted content
Please use the `sandbox` option with care, as it is still an experimental
feature. We are still not aware of the security implications of exposing some
Electron renderer APIs to the preload script, but here are some things to
consider before rendering untrusted content:
Rendering untrusted content in Electron is still somewhat uncharted territory,
though some apps are finding success (e.g. Beaker Browser). Our goal is to get
as close to Chrome as we can in terms of the security of sandboxed content, but
ultimately we will always be behind due to a few fundamental issues:
1. We do not have the dedicated resources or expertise that Chromium has to
apply to the security of its product. We do our best to make use of what we
have, to inherit everything we can from Chromium, and to respond quickly to
security issues, but Electron cannot be as secure as Chromium without the
resources that Chromium is able to dedicate.
2. Some security features in Chrome (such as Safe Browsing and Certificate
Transparency) require a centralized authority and dedicated servers, both of
which run counter to the goals of the Electron project. As such, we disable
those features in Electron, at the cost of the associated security they
would otherwise bring.
3. There is only one Chromium, whereas there are many thousands of apps built
on Electron, all of which behave slightly differently. Accounting for those
differences can yield a huge possibility space, and make it challenging to
ensure the security of the platform in unusual use cases.
4. We can't push security updates to users directly, so we rely on app vendors
to upgrade the version of Electron underlying their app in order for
security updates to reach users.
Here are some things to consider before rendering untrusted content:
- A preload script can accidentally leak privileged APIs to untrusted code,
unless [`contextIsolation`](../tutorial/security.md#3-enable-context-isolation-for-remote-content)
is also enabled.
- Some bug in V8 engine may allow malicious code to access the renderer preload
APIs, effectively granting full access to the system through the `remote`
module. Therefore, it is highly recommended to
[disable the `remote` module](../tutorial/security.md#15-disable-the-remote-module).
If disabling is not feasible, you should selectively
[filter the `remote` module](../tutorial/security.md#16-filter-the-remote-module).
Since rendering untrusted content in Electron is still uncharted territory,
the APIs exposed to the sandbox preload script should be considered more
unstable than the rest of Electron APIs, and may have breaking changes to fix
security issues.
- Some bug in the V8 engine may allow malicious code to access the renderer
preload APIs, effectively granting full access to the system through the
`remote` module. Therefore, it is highly recommended to [disable the `remote`
module](../tutorial/security.md#15-disable-the-remote-module).
If disabling is not feasible, you should selectively [filter the `remote`
module](../tutorial/security.md#16-filter-the-remote-module).
- While we make our best effort to backport Chromium security fixes to older
versions of Electron, we do not make a guarantee that every fix will be
backported. Your best chance at staying secure is to be on the latest stable
version of Electron.

View File

@@ -39,7 +39,7 @@ Returns:
* `message` String - The actual console message
* `versionId` Number - The version ID of the service worker that sent the log message
* `source` String - The type of source for this message. Can be `javascript`, `xml`, `network`, `console-api`, `storage`, `app-cache`, `rendering`, `security`, `deprecation`, `worker`, `violation`, `intervention`, `recommendation` or `other`.
* `level` Number - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
* `level` Number - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
* `sourceUrl` String - The URL the message came from
* `lineNumber` Number - The line number of the source that triggered this console message

View File

@@ -1,4 +1,5 @@
# MimeTypedBuffer Object
* `mimeType` String - The mimeType of the Buffer that you are sending.
* `mimeType` String (optional) - MIME type of the buffer.
* `charset` String (optional) - Charset of the buffer.
* `data` Buffer - The actual Buffer content.

View File

@@ -4,3 +4,4 @@
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](upload-data.md) (optional)
* `headers` Record<String, String>

View File

@@ -338,7 +338,7 @@ win.webContents.on('will-prevent-unload', (event) => {
})
```
#### Event: 'crashed'
#### Event: 'crashed' _Deprecated_
Returns:
@@ -347,6 +347,29 @@ Returns:
Emitted when the renderer process crashes or is killed.
**Deprecated:** This event is superceded by the `render-process-gone` event
which contains more information about why the render process dissapeared. It
isn't always because it crashed. The `killed` boolean can be replaced by
checking `reason === 'killed'` when you switch to that event.
#### Event: 'render-process-gone'
Returns:
* `event` Event
* `details` Object
* `reason` String - The reason the render process is gone. Possible values:
* `clean-exit` - Process exited with an exit code of zero
* `abnormal-exit` - Process exited with a non-zero exit code
* `killed` - Process was sent a SIGTERM or otherwise killed externally
* `crashed` - Process crashed
* `oom` - Process ran out of memory
* `launch-failure` - Process never successfully launched
* `integrity-failure` - Windows code integrity checks failed
Emitted when the renderer process unexpectedly dissapears. This is normally
because it was crashed or killed.
#### Event: 'unresponsive'
Emitted when the web page becomes unresponsive.
@@ -714,9 +737,9 @@ Emitted when a `<webview>` has been attached to this web contents.
Returns:
* `event` Event
* `level` Integer
* `message` String
* `line` Integer
* `level` Integer - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
* `message` String - The actual console message
* `line` Integer - The line number of the source that triggered this console message
* `sourceId` String
Emitted when the associated window logs a console message.
@@ -884,10 +907,10 @@ Returns `String` - The URL of the current web page.
```javascript
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')
let currentURL = win.webContents.getURL()
console.log(currentURL)
win.loadURL('http://github.com').then(() => {
const currentURL = win.webContents.getURL()
console.log(currentURL)
})
```
#### `contents.getTitle()`
@@ -1789,6 +1812,11 @@ Returns `Promise<void>` - Indicates whether the snapshot has been created succes
Takes a V8 heap snapshot and saves it to `filePath`.
#### `contents.getBackgroundThrottling()`
Returns `Boolean` - whether or not this WebContents will throttle animations and timers
when the page becomes backgrounded. This also affects the Page Visibility API.
#### `contents.setBackgroundThrottling(allowed)`
* `allowed` Boolean
@@ -1856,3 +1884,8 @@ A [`Debugger`](debugger.md) instance for this webContents.
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
[SCA]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
[`postMessage`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
#### `contents.backgroundThrottling`
A `Boolean` property that determines whether or not this WebContents will throttle animations and timers
when the page becomes backgrounded. This also affects the Page Visibility API.

View File

@@ -162,10 +162,14 @@ this limitation.
* `error` Error
Returns `Promise<any>` - A promise that resolves with the result of the executed
code or is rejected if execution throws or results in a rejected promise.
code or is rejected if execution could not start.
Works like `executeJavaScript` but evaluates `scripts` in an isolated context.
Note that when the execution of script fails, the returned promise will not
reject and the `result` would be `undefined`. This is because Chromium does not
dispatch errors of isolated worlds to foreign worlds.
### `webFrame.setIsolatedWorldInfo(worldId, info)`
* `worldId` Integer - The ID of the world to run the javascript in, `0` is the default world, `999` is the world used by Electrons `contextIsolation` feature. Chrome extensions reserve the range of IDs in `[1 << 20, 1 << 29)`. You can provide any integer here.
* `info` Object

View File

@@ -755,9 +755,9 @@ Fired when page leaves fullscreen triggered by HTML API.
Returns:
* `level` Integer
* `message` String
* `line` Integer
* `level` Integer - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
* `message` String - The actual console message
* `line` Integer - The line number of the source that triggered this console message
* `sourceId` String
Fired when the guest window logs a console message.

View File

@@ -12,8 +12,92 @@ This document uses the following convention to categorize breaking changes:
- **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
- **Removed:** An API or feature was removed, and is no longer supported by Electron.
## Planned Breaking API Changes (12.0)
### Removed: `crashReporter` methods in the renderer process
The following `crashReporter` methods are no longer available in the renderer
process:
- `crashReporter.start`
- `crashReporter.getLastCrashReport`
- `crashReporter.getUploadedReports`
- `crashReporter.getUploadToServer`
- `crashReporter.setUploadToServer`
- `crashReporter.getCrashesDirectory`
They should be called only from the main process.
See [#23265](https://github.com/electron/electron/pull/23265) for more details.
### Default Changed: `crashReporter.start({ compress: true })`
The default value of the `compress` option to `crashReporter.start` has changed
from `false` to `true`. This means that crash dumps will be uploaded to the
crash ingestion server with the `Content-Encoding: gzip` header, and the body
will be compressed.
If your crash ingestion server does not support compressed payloads, you can
turn off compression by specifying `{ compress: false }` in the crash reporter
options.
## Planned Breaking API Changes (11.0)
There are no breaking changes planned for 11.0.
## Planned Breaking API Changes (10.0)
### Deprecated: `companyName` argument to `crashReporter.start()`
The `companyName` argument to `crashReporter.start()`, which was previously
required, is now optional, and further, is deprecated. To get the same
behavior in a non-deprecated way, you can pass a `companyName` value in
`globalExtra`.
```js
// Deprecated in Electron 10
crashReporter.start({ companyName: 'Umbrella Corporation' })
// Replace with
crashReporter.start({ globalExtra: { _companyName: 'Umbrella Corporation' } })
```
### Deprecated: `crashReporter.getCrashesDirectory()`
The `crashReporter.getCrashesDirectory` method has been deprecated. Usage
should be replaced by `app.getPath('crashDumps')`.
```js
// Deprecated in Electron 10
crashReporter.getCrashesDirectory()
// Replace with
app.getPath('crashDumps')
```
### Deprecated: `crashReporter` methods in the renderer process
Calling the following `crashReporter` methods from the renderer process is
deprecated:
- `crashReporter.start`
- `crashReporter.getLastCrashReport`
- `crashReporter.getUploadedReports`
- `crashReporter.getUploadToServer`
- `crashReporter.setUploadToServer`
- `crashReporter.getCrashesDirectory`
The only non-deprecated methods remaining in the `crashReporter` module in the
renderer are `addExtraParameter`, `removeExtraParameter` and `getParameters`.
All above methods remain non-deprecated when called from the main process.
See [#23265](https://github.com/electron/electron/pull/23265) for more details.
### Deprecated: `crashReporter.start({ compress: false })`
Setting `{ compress: false }` in `crashReporter.start` is deprecated. Nearly
all crash ingestion servers support gzip compression. This option will be
removed in a future version of Electron.
### Removed: Browser Window Affinity
The `affinity` option when constructing a new `BrowserWindow` will be removed

View File

@@ -23,4 +23,3 @@ For guides on Electron app development, see
* [Debugging on macOS](debugging-instructions-macos.md)
* [Setting Up Symbol Server in Debugger](setting-up-symbol-server.md)
* [Patches](patches.md)
* [Upgrading Node](upgrading-node.md)

View File

@@ -1,121 +0,0 @@
# Upgrading Node
## Discussion
Chromium and Node.js both depend on V8, and Electron contains
only a single copy of V8, so it's important to ensure that the
version of V8 chosen is compatible with the build's version of
Node.js and Chromium.
Upgrading Node is much easier than upgrading Chromium, so fewer
conflicts arise if one upgrades Chromium first, then chooses the
upstream Node release whose version of V8 is closest to the one
Chromium contains.
Electron has its own [Node fork](https://github.com/electron/node)
with modifications for the V8 build details mentioned above
and for exposing API needed by Electron. Once an upstream Node
release is chosen, it's placed in a branch in Electron's Node fork
and any Electron Node patches are applied there.
Another factor is that the Node project patches its version of V8.
As mentioned above, Electron builds everything with a single copy
of V8, so Node's V8 patches must be ported to that copy.
Once all of Electron's dependencies are building and using the same
copy of V8, the next step is to fix any Electron code issues caused
by the Node upgrade.
[FIXME] something about a Node debugger in Atom that we (e.g. deepak)
use and need to confirm doesn't break with the Node upgrade?
So in short, the primary steps are:
1. Update Electron's Node fork to the desired version
2. Backport Node's V8 patches to our copy of V8
3. Update the GN build files, porting changes from node's GYP files
4. Update Electron's DEPS to use new version of Node
## Updating Electron's Node [fork](https://github.com/electron/node)
1. Ensure that `master` on `electron/node` has updated release tags from `nodejs/node`
2. Create a branch in https://github.com/electron/node: `electron-node-vX.X.X` where the base that you're branching from is the tag for the desired update
- `vX.X.X` Must use a version of Node compatible with our current version of Chromium
3. Re-apply our commits from the previous version of Node we were using (`vY.Y.Y`) to `v.X.X.X`
- Check release tag and select the range of commits we need to re-apply
- Cherry-pick commit range:
1. Checkout both `vY.Y.Y` & `v.X.X.X`
2. `git cherry-pick FIRST_COMMIT_HASH..LAST_COMMIT_HASH`
- Resolve merge conflicts in each file encountered, then:
1. `git add <conflict-file>`
2. `git cherry-pick --continue`
3. Repeat until finished
## Updating [V8](https://github.com/electron/node/src/V8) Patches
We need to generate a patch file from each patch that Node
applies to V8.
```sh
$ cd third_party/electron_node
$ CURRENT_NODE_VERSION=vX.Y.Z
# Find the last commit with the message "deps: update V8 to <some version>"
# This commit corresponds to Node resetting V8 to its pristine upstream
# state at the stated version.
$ LAST_V8_UPDATE="$(git log --grep='^deps: update V8' --format='%H' -1 deps/v8)"
# This creates a patch file containing all changes in deps/v8 from
# $LAST_V8_UPDATE up to the current Node version, formatted in a way that
# it will apply cleanly to the V8 repository (i.e. with `deps/v8`
# stripped off the path and excluding the v8/gypfiles directory, which
# isn't present in V8.
$ git format-patch \
--relative=deps/v8 \
$LAST_V8_UPDATE..$CURRENT_NODE_VERSION \
deps/v8 \
':(exclude)deps/v8/gypfiles' \
--stdout \
> ../../electron/common/patches/v8/node_v8_patches.patch
```
This list of patches will probably include one that claims to
make the V8 API backwards-compatible with a previous version of
V8. Unfortunately, those patches almost always change the V8 API
in a way that is incompatible with Chromium.
It's usually easier to update Node to work without the
compatibility patch than to update Chromium to work with the
compatibility patch, so it's recommended to revert the
compatibility patch and fix any errors that arise when compiling
Node.
## Update Electron's `DEPS` file
Update the `DEPS` file in the root of
[electron/electron](https://github.com/electron/electron) to
point to the git hash of the updated Node.
## Notes
- Node maintains its own fork of V8
- They backport a small amount of things as needed
- Documentation in Node about how [they work with V8](https://nodejs.org/api/v8.html)
- We update code such that we only use one copy of V8 across all of Electron
- E.g Electron, Chromium, and Node.js
- We dont track upstream closely due to logistics:
- Upstream uses multiple repos and so merging into a single repo
would result in lost history. So we only update when were planning
a Node version bump in Electron.
- Chromium is large and time-consuming to update, so we typically
choose the Node version based on which of its releases has a version
of V8 thats closest to the version in Chromium that were using.
- We sometimes have to wait for the next periodic Node release
because it will sync more closely with the version of V8 in the new Chromium
- Electron keeps all its patches in the repo because its simpler than
maintaining different repos for patches for each upstream project.
- Crashpad, Node.js, Chromium, Skia etc. patches are all kept in the same place
- Building Node:
- We maintain our own GN build files for Node.js to make it easier to ensure
that eevrything is built with the same compiler flags.
This means that every time we upgrade Node.js we have to do a modest amount of
work to synchronize the GN files with the upstream GYP files.

View File

@@ -1,3 +0,0 @@
# Electron App Feedback Program
Electron is working on building a streamlined release process and having faster releases. To help with that, we have the App Feedback Program for large-scale Electron apps to test our beta releases and report app-specific issues to the Electron team. We use this program to help us prioritize work and get applications upgraded to the next stable release as soon as possible. There are a few requirements we expect from participants, such as attending short, online weekly check-ins. Please visit the [blog post](https://electronjs.org/blog/app-feedback-program) for details and sign-up.

View File

@@ -0,0 +1,70 @@
# Context Isolation
## What is it?
Context Isolation is a feature that ensures that both your `preload` scripts and Electron's internal logic run in a separate context to the website you load in a [`webContents`](../api/web-contents.md). This is important for security purposes as it helps prevent the website from accessing Electron internals or the powerful APIs your preload script has access to.
This means that the `window` object that your preload script has access to is actually a **different** object than the website would have access to. For example, if you set `window.hello = 'wave'` in your preload script and context isolation is enabled `window.hello` will be undefined if the website tries to access it.
Every single application should have context isolation enabled and from Electron 12 it will be enabled by default.
## How do I enable it?
From Electron 12, it will be enabled by default. For lower versions it is an option in the `webPreferences` option when constructing `new BrowserWindow`'s.
```javascript
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: true
}
})
```
## Migration
> I used to provide APIs from my preload script using `window.X = apiObject` now what?
Exposing APIs from your preload script to the loaded website is a common usecase and there is a dedicated module in Electron to help you do this in a painless way.
**Before: With context isolation disabled**
```javascript
window.myAPI = {
doAThing: () => {}
}
```
**After: With context isolation enabled**
```javascript
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('myAPI', {
doAThing: () => {}
})
```
The [`contextBridge`](../api/context-bridge.md) module can be used to **safely** expose APIs from the isolated context your preload script runs in to the context the website is running in. The API will also be accessible from the website on `window.myAPI` just like it was before.
You should read the `contextBridge` documentation linked above to fully understand its limitations. For instance you can't send custom prototypes or symbols over the bridge.
## Security Considerations
Just enabling `contextIsolation` and using `contextBridge` does not automatically mean that everything you do is safe. For instance this code is **unsafe**.
```javascript
// ❌ Bad code
contextBridge.exposeInMainWorld('myAPI', {
send: ipcRenderer.send
})
```
It directly exposes a powerful API without any kind of argument filtering. This would allow any website to send arbitrary IPC messages which you do not want to be possible. The correct way to expose IPC-based APIs would instead be to provide one method per IPC message.
```javascript
// ✅ Good code
contextBridge.exposeInMainWorld('myAPI', {
loadPreferences: () => ipcRenderer.invoke('load-prefs')
})
```

View File

@@ -64,7 +64,7 @@ Following Devtools Extensions are tested and guaranteed to work in Electron:
* [jQuery Debugger](https://chrome.google.com/webstore/detail/jquery-debugger/dbhhnnnpaeobfddmlalhnehgclcmjimi)
* [AngularJS Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk)
* [Vue.js devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
* [Cerebral Debugger](https://cerebraljs.com/docs/introduction/debugger.html)
* [Cerebral Debugger](https://cerebraljs.com/docs/introduction/devtools.html)
* [Redux DevTools Extension](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd)
* [MobX Developer Tools](https://chrome.google.com/webstore/detail/mobx-developer-tools/pfgnfdagidkfgccljigdamigbcnndkod)

View File

@@ -4,15 +4,17 @@
* We strive for weekly beta releases, however we often release more betas than scheduled.
* All dates are our goals but there may be reasons for adjusting the stable deadline, such as security bugs.
* Take a look at the [5.0.0 Timeline blog post](https://electronjs.org/blog/electron-5-0-timeline) for info about publicizing our release dates.
* Since Electron 6.0, we've been targetting every other Chromium version and releasing our stable on the same day as Chrome stable. You can reference Chromium's release schedule [here](https://chromiumdash.appspot.com/schedule). See [Electron's new release cadence blog post](https://www.electronjs.org/blog/12-week-cadence) for more details on our release schedule.
| Version | -beta.1 | Stable | Chrome | Node |
| ------- | ------- | ------ | ------ | ---- |
| 2.0.0 | 2018-02-21 | 2018-05-01 | M61 | v8 |
| 3.0.0 | 2018-06-21 | 2018-09-18 | M66 | v10 |
| 4.0.0 | 2018-10-11 | 2018-12-20 | M69 | v10 |
| 5.0.0 | 2019-01-22 | 2019-04-24 | M73 | v12 |
| 6.0.0 | 2019-05-01 | 2019-07-30 | M76 | v12 |
| 7.0.0 | 2019-08-01 | 2019-10-22 | M78 | v12 |
| 8.0.0 | 2019-10-24 | 2020-02-04 | M80 | v12 |
| 9.0.0 | 2020-02-06 | 2020-05-19 | M83 | v12 |
| 10.0.0 | TBD | TBD | TBD | TBD |
| 2.0.0 | 2018-02-21 | 2018-05-01 | M61 | v8.9 |
| 3.0.0 | 2018-06-21 | 2018-09-18 | M66 | v10.2 |
| 4.0.0 | 2018-10-11 | 2018-12-20 | M69 | v10.11 |
| 5.0.0 | 2019-01-22 | 2019-04-24 | M73 | v12.0 |
| 6.0.0 | 2019-05-01 | 2019-07-30 | M76 | v12.4 |
| 7.0.0 | 2019-08-01 | 2019-10-22 | M78 | v12.8 |
| 8.0.0 | 2019-10-24 | 2020-02-04 | M80 | v12.13 |
| 9.0.0 | 2020-02-06 | 2020-05-19 | M83 | v12.14 |
| 10.0.0 | 2020-05-21 | 2020-08-25 | M85 | v12.x |
| 11.0.0 | TBD | TBD | TBD| TBD |

View File

@@ -44,23 +44,10 @@ run the main process. An example of your `package.json` might look like this:
```
__Note__: If the `main` field is not present in `package.json`, Electron will
attempt to load an `index.js` (as Node.js does). If this was actually
a simple Node application, you would add a `start` script that instructs `node`
to execute the current package:
attempt to load an `index.js` (as Node.js does).
```json
{
"name": "your-app",
"version": "0.1.0",
"main": "main.js",
"scripts": {
"start": "node ."
}
}
```
Turning this Node application into an Electron application is quite simple - we
merely replace the `node` runtime with the `electron` runtime.
By default, `npm start` would run the main script with Node.js. in order to make
it run with Electron, you can add a `start` script:
```json
{

View File

@@ -352,7 +352,7 @@ Many users of Electron start with an entirely web-based app that they're
turning into a desktop application. As web developers, we are used to loading
resources from a variety of content delivery networks. Now that you are
shipping a proper desktop application, attempt to "cut the cord" where possible
- and avoid letting your users wait for resources that never change and could
and avoid letting your users wait for resources that never change and could
easily be included in your app.
A typical example is Google Fonts. Many developers make use of Google's

View File

@@ -239,51 +239,10 @@ to enable this behavior.
Even when you use `nodeIntegration: false` to enforce strong isolation and
prevent the use of Node primitives, `contextIsolation` must also be used.
### Why?
### Why & How?
Context isolation allows each of the scripts running in the renderer to make
changes to its JavaScript environment without worrying about conflicting with
the scripts in the Electron API or the preload script.
While still an experimental Electron feature, context isolation adds an
additional layer of security. It creates a new JavaScript world for Electron
APIs and preload scripts, which mitigates so-called "Prototype Pollution" attacks.
At the same time, preload scripts still have access to the `document` and
`window` objects. In other words, you're getting a decent return on a likely
very small investment.
### How?
```js
// Main process
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: true,
preload: path.join(app.getAppPath(), 'preload.js')
}
})
```
```js
// Preload script
// Set a variable in the page before it loads
webFrame.executeJavaScript('window.foo = "foo";')
// The loaded page will not be able to access this, it is only available
// in this context
window.bar = 'bar'
document.addEventListener('DOMContentLoaded', () => {
// Will log out 'undefined' since window.foo is only available in the main
// context
console.log(window.foo)
// Will log out 'bar' since window.bar is available in this context
console.log(window.bar)
})
```
For more information on what `contextIsolation` is and how to enable it please
see our dedicated [Context Isolation](context-isolation.md) document.
## 4) Handle Session Permission Requests From Remote Content

View File

@@ -0,0 +1,74 @@
# SpellChecker
Electron has built-in support for Chromium's spellchecker since Electron 8. On Windows and Linux this is powered by Hunspell dictionaries, and on macOS it makes use of the native spellchecker APIs.
## How to enable the spellchecker?
For Electron 9 and higher the spellchecker is enabled by default. For Electron 8 you need to enable it in `webPreferences`.
```js
const myWindow = new BrowserWindow({
webPreferences: {
spellcheck: true
}
})
```
## How to set the languages the spellchecker uses?
On macOS as we use the native APIs there is no way to set the language that the spellchecker uses. By default on macOS the native spellchecker will automatically detect the language being used for you.
For Windows and Linux there are a few Electron APIs you should use to set the languages for the spellchecker.
```js
// Sets the spellchecker to check English US and French
myWindow.session.setSpellCheckerLanguages(['en-US', 'fr'])
// An array of all available language codes
const possibleLanguages = myWindow.session.availableSpellCheckerLanguages
```
By default the spellchecker will enable the language matching the current OS locale.
## How do I put the results of the spellchecker in my context menu?
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
const { Menu, MenuItem } = require('electron')
myWindow.webContents.on('context-menu', (event, params) => {
const menu = new Menu()
// Add each spelling suggestion
for (const suggestion of params.dictionarySuggestions) {
menu.append(new MenuItem({
label: suggestion,
click: () => mainWindow.webContents.replaceMisspelling(suggestion)
}))
}
// Allow users to add the misspelled word to the dictionary
if (params.misspelledWord) {
menu.append(
new MenuItem({
label: 'Add to dictionary',
click: () => mainWindow.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
})
)
}
menu.popup()
})
```
## Does the spellchecker use any Google services?
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/')
```
Check out the docs for [`session.setSpellCheckerDictionaryDownloadURL`](https://www.electronjs.org/docs/api/session#sessetspellcheckerdictionarydownloadurlurl) for more information on where to get the dictionary files from and how you need to host them.

View File

@@ -58,9 +58,9 @@ threshold, we will attempt to support backwards compatibility beyond two version
until the maintainers feel the maintenance burden is too high to continue doing so.
### Currently supported versions
- 8.1.x
- 7.1.x
- 6.1.x
- 9.x.y
- 8.x.y
- 7.x.y
### End-of-life

View File

@@ -43,7 +43,6 @@ auto_filenames = {
"docs/api/power-monitor.md",
"docs/api/power-save-blocker.md",
"docs/api/process.md",
"docs/api/protocol-ns.md",
"docs/api/protocol.md",
"docs/api/remote.md",
"docs/api/sandbox-option.md",
@@ -135,20 +134,19 @@ auto_filenames = {
]
sandbox_bundle_deps = [
"lib/browser/api/module-keys.js",
"lib/common/api/clipboard.js",
"lib/browser/api/module-names.ts",
"lib/common/api/clipboard.ts",
"lib/common/api/deprecate.ts",
"lib/common/api/module-list.ts",
"lib/common/api/native-image.js",
"lib/common/api/shell.js",
"lib/common/crash-reporter.js",
"lib/common/api/native-image.ts",
"lib/common/api/shell.ts",
"lib/common/define-properties.ts",
"lib/common/electron-binding-setup.ts",
"lib/common/type-utils.ts",
"lib/common/web-view-methods.ts",
"lib/common/webpack-globals-provider.ts",
"lib/renderer/api/context-bridge.ts",
"lib/renderer/api/crash-reporter.js",
"lib/renderer/api/crash-reporter.ts",
"lib/renderer/api/desktop-capturer.ts",
"lib/renderer/api/ipc-renderer.ts",
"lib/renderer/api/remote.js",
@@ -168,10 +166,12 @@ auto_filenames = {
"lib/renderer/window-setup.ts",
"lib/sandboxed_renderer/api/exports/electron.ts",
"lib/sandboxed_renderer/api/module-list.ts",
"lib/sandboxed_renderer/init.js",
"lib/sandboxed_renderer/init.ts",
"package.json",
"tsconfig.electron.json",
"tsconfig.json",
"typings/internal-ambient.d.ts",
"typings/internal-electron.d.ts",
]
isolated_bundle_deps = [
@@ -182,6 +182,8 @@ auto_filenames = {
"package.json",
"tsconfig.electron.json",
"tsconfig.json",
"typings/internal-ambient.d.ts",
"typings/internal-electron.d.ts",
]
browser_bundle_deps = [
@@ -190,14 +192,15 @@ auto_filenames = {
"lib/browser/api/auto-updater/auto-updater-native.js",
"lib/browser/api/auto-updater/auto-updater-win.js",
"lib/browser/api/auto-updater/squirrel-update-win.js",
"lib/browser/api/browser-view.js",
"lib/browser/api/browser-view.ts",
"lib/browser/api/browser-window.js",
"lib/browser/api/content-tracing.js",
"lib/browser/api/crash-reporter.js",
"lib/browser/api/content-tracing.ts",
"lib/browser/api/crash-reporter.ts",
"lib/browser/api/desktop-capturer.ts",
"lib/browser/api/dialog.js",
"lib/browser/api/exports/electron.ts",
"lib/browser/api/global-shortcut.js",
"lib/browser/api/in-app-purchase.js",
"lib/browser/api/global-shortcut.ts",
"lib/browser/api/in-app-purchase.ts",
"lib/browser/api/ipc-main.ts",
"lib/browser/api/menu-item-roles.js",
"lib/browser/api/menu-item.js",
@@ -207,23 +210,22 @@ auto_filenames = {
"lib/browser/api/module-list.ts",
"lib/browser/api/native-theme.ts",
"lib/browser/api/net-log.js",
"lib/browser/api/net.js",
"lib/browser/api/notification.js",
"lib/browser/api/net.ts",
"lib/browser/api/notification.ts",
"lib/browser/api/power-monitor.ts",
"lib/browser/api/power-save-blocker.js",
"lib/browser/api/power-save-blocker.ts",
"lib/browser/api/protocol.ts",
"lib/browser/api/screen.ts",
"lib/browser/api/session.js",
"lib/browser/api/session.ts",
"lib/browser/api/system-preferences.ts",
"lib/browser/api/top-level-window.js",
"lib/browser/api/touch-bar.js",
"lib/browser/api/tray.js",
"lib/browser/api/view.js",
"lib/browser/api/views/image-view.js",
"lib/browser/api/web-contents-view.js",
"lib/browser/api/tray.ts",
"lib/browser/api/view.ts",
"lib/browser/api/views/image-view.ts",
"lib/browser/api/web-contents-view.ts",
"lib/browser/api/web-contents.js",
"lib/browser/chrome-extension-shim.js",
"lib/browser/crash-reporter-init.js",
"lib/browser/default-menu.ts",
"lib/browser/desktop-capturer.ts",
"lib/browser/devtools.ts",
@@ -239,12 +241,11 @@ auto_filenames = {
"lib/browser/remote/server.ts",
"lib/browser/rpc-server.js",
"lib/browser/utils.ts",
"lib/common/api/clipboard.js",
"lib/common/api/clipboard.ts",
"lib/common/api/deprecate.ts",
"lib/common/api/module-list.ts",
"lib/common/api/native-image.js",
"lib/common/api/shell.js",
"lib/common/crash-reporter.js",
"lib/common/api/native-image.ts",
"lib/common/api/shell.ts",
"lib/common/define-properties.ts",
"lib/common/electron-binding-setup.ts",
"lib/common/init.ts",
@@ -258,16 +259,17 @@ auto_filenames = {
"package.json",
"tsconfig.electron.json",
"tsconfig.json",
"typings/internal-ambient.d.ts",
"typings/internal-electron.d.ts",
]
renderer_bundle_deps = [
"lib/browser/api/module-keys.js",
"lib/common/api/clipboard.js",
"lib/browser/api/module-names.ts",
"lib/common/api/clipboard.ts",
"lib/common/api/deprecate.ts",
"lib/common/api/module-list.ts",
"lib/common/api/native-image.js",
"lib/common/api/shell.js",
"lib/common/crash-reporter.js",
"lib/common/api/native-image.ts",
"lib/common/api/shell.ts",
"lib/common/define-properties.ts",
"lib/common/electron-binding-setup.ts",
"lib/common/init.ts",
@@ -276,7 +278,7 @@ auto_filenames = {
"lib/common/web-view-methods.ts",
"lib/common/webpack-globals-provider.ts",
"lib/renderer/api/context-bridge.ts",
"lib/renderer/api/crash-reporter.js",
"lib/renderer/api/crash-reporter.ts",
"lib/renderer/api/desktop-capturer.ts",
"lib/renderer/api/exports/electron.ts",
"lib/renderer/api/ipc-renderer.ts",
@@ -301,16 +303,17 @@ auto_filenames = {
"package.json",
"tsconfig.electron.json",
"tsconfig.json",
"typings/internal-ambient.d.ts",
"typings/internal-electron.d.ts",
]
worker_bundle_deps = [
"lib/browser/api/module-keys.js",
"lib/common/api/clipboard.js",
"lib/browser/api/module-names.ts",
"lib/common/api/clipboard.ts",
"lib/common/api/deprecate.ts",
"lib/common/api/module-list.ts",
"lib/common/api/native-image.js",
"lib/common/api/shell.js",
"lib/common/crash-reporter.js",
"lib/common/api/native-image.ts",
"lib/common/api/shell.ts",
"lib/common/define-properties.ts",
"lib/common/electron-binding-setup.ts",
"lib/common/init.ts",
@@ -318,7 +321,7 @@ auto_filenames = {
"lib/common/type-utils.ts",
"lib/common/webpack-globals-provider.ts",
"lib/renderer/api/context-bridge.ts",
"lib/renderer/api/crash-reporter.js",
"lib/renderer/api/crash-reporter.ts",
"lib/renderer/api/desktop-capturer.ts",
"lib/renderer/api/exports/electron.ts",
"lib/renderer/api/ipc-renderer.ts",
@@ -333,5 +336,7 @@ auto_filenames = {
"package.json",
"tsconfig.electron.json",
"tsconfig.json",
"typings/internal-ambient.d.ts",
"typings/internal-electron.d.ts",
]
}

View File

@@ -31,6 +31,8 @@ filenames = {
"shell/app/command_line_args.h",
"shell/app/electron_content_client.cc",
"shell/app/electron_content_client.h",
"shell/app/electron_crash_reporter_client.cc",
"shell/app/electron_crash_reporter_client.h",
"shell/app/electron_main_delegate.cc",
"shell/app/electron_main_delegate.h",
"shell/app/electron_main_delegate_mac.h",
@@ -51,6 +53,8 @@ filenames = {
"shell/browser/api/electron_api_content_tracing.cc",
"shell/browser/api/electron_api_cookies.cc",
"shell/browser/api/electron_api_cookies.h",
"shell/browser/api/electron_api_crash_reporter.cc",
"shell/browser/api/electron_api_crash_reporter.h",
"shell/browser/api/electron_api_data_pipe_holder.cc",
"shell/browser/api/electron_api_data_pipe_holder.h",
"shell/browser/api/electron_api_debugger.cc",
@@ -170,7 +174,6 @@ filenames = {
"shell/browser/electron_javascript_dialog_manager.h",
"shell/browser/electron_navigation_throttle.cc",
"shell/browser/electron_navigation_throttle.h",
"shell/browser/electron_paths.h",
"shell/browser/electron_permission_manager.cc",
"shell/browser/electron_permission_manager.h",
"shell/browser/electron_quota_permission_context.cc",
@@ -398,6 +401,8 @@ filenames = {
"shell/browser/ui/views/submenu_button.h",
"shell/browser/ui/views/win_frame_view.cc",
"shell/browser/ui/views/win_frame_view.h",
"shell/browser/ui/win/dialog_thread.cc",
"shell/browser/ui/win/dialog_thread.h",
"shell/browser/ui/win/electron_desktop_native_widget_aura.cc",
"shell/browser/ui/win/electron_desktop_native_widget_aura.h",
"shell/browser/ui/win/electron_desktop_window_tree_host_win.cc",
@@ -442,7 +447,6 @@ filenames = {
"shell/common/api/electron_api_clipboard.h",
"shell/common/api/electron_api_clipboard_mac.mm",
"shell/common/api/electron_api_command_line.cc",
"shell/common/api/electron_api_crash_reporter.cc",
"shell/common/api/electron_api_key_weak_map.h",
"shell/common/api/electron_api_native_image.cc",
"shell/common/api/electron_api_native_image.h",
@@ -452,6 +456,8 @@ filenames = {
"shell/common/api/electron_bindings.cc",
"shell/common/api/electron_bindings.h",
"shell/common/api/features.cc",
"shell/common/api/object_life_monitor.cc",
"shell/common/api/object_life_monitor.h",
"shell/common/application_info.cc",
"shell/common/application_info.h",
"shell/common/application_info_linux.cc",
@@ -465,22 +471,13 @@ filenames = {
"shell/common/asar/scoped_temporary_file.h",
"shell/common/color_util.cc",
"shell/common/color_util.h",
"shell/common/crash_reporter/crash_reporter.cc",
"shell/common/crash_reporter/crash_reporter.h",
"shell/common/crash_reporter/crash_reporter_linux.cc",
"shell/common/crash_reporter/crash_reporter_linux.h",
"shell/common/crash_reporter/crash_reporter_mac.h",
"shell/common/crash_reporter/crash_reporter_mac.mm",
"shell/common/crash_reporter/crash_reporter_win.cc",
"shell/common/crash_reporter/crash_reporter_win.h",
"shell/common/crash_reporter/linux/crash_dump_handler.cc",
"shell/common/crash_reporter/linux/crash_dump_handler.h",
"shell/common/crash_reporter/win/crash_service_main.cc",
"shell/common/crash_reporter/win/crash_service_main.h",
"shell/common/crash_keys.cc",
"shell/common/crash_keys.h",
"shell/common/electron_command_line.cc",
"shell/common/electron_command_line.h",
"shell/common/electron_constants.cc",
"shell/common/electron_constants.h",
"shell/common/electron_paths.h",
"shell/common/gin_converters/accelerator_converter.cc",
"shell/common/gin_converters/accelerator_converter.h",
"shell/common/gin_converters/blink_converter.cc",
@@ -502,6 +499,8 @@ filenames = {
"shell/common/gin_converters/net_converter.cc",
"shell/common/gin_converters/net_converter.h",
"shell/common/gin_converters/std_converter.h",
"shell/common/gin_converters/time_converter.cc",
"shell/common/gin_converters/time_converter.h",
"shell/common/gin_converters/value_converter.cc",
"shell/common/gin_converters/value_converter.h",
"shell/common/gin_helper/arguments.cc",
@@ -579,10 +578,9 @@ filenames = {
"shell/common/world_ids.h",
"shell/renderer/api/context_bridge/object_cache.cc",
"shell/renderer/api/context_bridge/object_cache.h",
"shell/renderer/api/context_bridge/render_frame_function_store.cc",
"shell/renderer/api/context_bridge/render_frame_function_store.h",
"shell/renderer/api/electron_api_context_bridge.cc",
"shell/renderer/api/electron_api_context_bridge.h",
"shell/renderer/api/electron_api_crash_reporter_renderer.cc",
"shell/renderer/api/electron_api_ipc_renderer.cc",
"shell/renderer/api/electron_api_spell_check_client.cc",
"shell/renderer/api/electron_api_spell_check_client.h",

View File

@@ -1,11 +1,10 @@
'use strict';
import { EventEmitter } from 'events';
const { EventEmitter } = require('events');
const { BrowserView } = process.electronBinding('browser_view');
Object.setPrototypeOf(BrowserView.prototype, EventEmitter.prototype);
BrowserView.fromWebContents = (webContents) => {
BrowserView.fromWebContents = (webContents: Electron.WebContents) => {
for (const view of BrowserView.getAllViews()) {
if (view.webContents.equal(webContents)) return view;
}
@@ -13,4 +12,4 @@ BrowserView.fromWebContents = (webContents) => {
return null;
};
module.exports = BrowserView;
export default BrowserView;

View File

@@ -157,6 +157,9 @@ Object.assign(BrowserWindow.prototype, {
setTouchBar (touchBar) {
electron.TouchBar._setOnWindow(touchBar, this);
},
getBackgroundThrottling () {
return this.webContents.getBackgroundThrottling();
},
setBackgroundThrottling (allowed) {
this.webContents.setBackgroundThrottling(allowed);
}

View File

@@ -1,2 +0,0 @@
'use strict';
module.exports = process.electronBinding('content_tracing');

View File

@@ -0,0 +1 @@
export default process.electronBinding('content_tracing');

View File

@@ -1,12 +0,0 @@
'use strict';
const CrashReporter = require('@electron/internal/common/crash-reporter');
const { crashReporterInit } = require('@electron/internal/browser/crash-reporter-init');
class CrashReporterMain extends CrashReporter {
init (options) {
return crashReporterInit(options);
}
}
module.exports = new CrashReporterMain();

View File

@@ -1,47 +1,39 @@
'use strict';
import { app, deprecate } from 'electron';
const binding = process.electronBinding('crash_reporter');
class CrashReporter {
constructor () {
this.productName = null;
this.crashesDirectory = null;
}
init (options) {
throw new Error('Not implemented');
}
start (options) {
if (options == null) options = {};
start (options: Electron.CrashReporterStartOptions) {
const {
productName,
productName = app.name,
companyName,
extra = {},
globalExtra = {},
ignoreSystemCrashHandler = false,
submitURL,
uploadToServer = true,
rateLimit = false,
compress = false
} = options;
} = options || {};
if (companyName == null) throw new Error('companyName is a required option to crashReporter.start');
if (submitURL == null) throw new Error('submitURL is a required option to crashReporter.start');
const ret = this.init({
submitURL,
productName
});
if (!compress) {
deprecate.log('Sending uncompressed crash reports is deprecated and will be removed in a future version of Electron. Set { compress: true } to opt-in to the new behavior. Crash reports will be uploaded gzipped, which most crash reporting servers support.');
}
this.productName = ret.productName;
this.crashesDirectory = ret.crashesDirectory;
const appVersion = app.getVersion();
if (extra._productName == null) extra._productName = ret.productName;
if (extra._companyName == null) extra._companyName = companyName;
if (extra._version == null) extra._version = ret.appVersion;
if (companyName && globalExtra._companyName == null) globalExtra._companyName = companyName;
binding.start(submitURL, ret.crashesDirectory, uploadToServer, ignoreSystemCrashHandler, rateLimit, compress, extra);
const globalExtraAmended = {
_productName: productName,
_version: appVersion,
...globalExtra
};
binding.start(submitURL, uploadToServer,
ignoreSystemCrashHandler, rateLimit, compress, globalExtraAmended, extra, false);
}
getLastCrashReport () {
@@ -55,17 +47,12 @@ class CrashReporter {
return (reports.length > 0) ? reports[0] : null;
}
getUploadedReports () {
const crashDir = this.getCrashesDirectory();
if (!crashDir) {
throw new Error('crashReporter has not been started');
}
return binding.getUploadedReports(crashDir);
getUploadedReports (): Electron.CrashReport[] {
return binding.getUploadedReports();
}
getCrashesDirectory () {
return this.crashesDirectory;
return app.getPath('crashDumps');
}
getUploadToServer () {
@@ -76,7 +63,7 @@ class CrashReporter {
}
}
setUploadToServer (uploadToServer) {
setUploadToServer (uploadToServer: boolean) {
if (process.type === 'browser') {
return binding.setUploadToServer(uploadToServer);
} else {
@@ -84,11 +71,11 @@ class CrashReporter {
}
}
addExtraParameter (key, value) {
addExtraParameter (key: string, value: string) {
binding.addExtraParameter(key, value);
}
removeExtraParameter (key) {
removeExtraParameter (key: string) {
binding.removeExtraParameter(key);
}
@@ -97,4 +84,4 @@ class CrashReporter {
}
}
module.exports = CrashReporter;
export default new CrashReporter();

View File

@@ -0,0 +1,5 @@
import { getSourcesImpl } from '@electron/internal/browser/desktop-capturer';
export async function getSources (options: Electron.SourcesOptions) {
return getSourcesImpl(null, options);
}

View File

@@ -1,3 +0,0 @@
'use strict';
module.exports = process.electronBinding('global_shortcut').globalShortcut;

View File

@@ -0,0 +1 @@
export default process.electronBinding('global_shortcut').globalShortcut;

View File

@@ -1,22 +1,24 @@
'use strict';
import { EventEmitter } from 'events';
const { deprecate } = require('electron');
let _inAppPurchase;
if (process.platform === 'darwin') {
const { EventEmitter } = require('events');
const { inAppPurchase, InAppPurchase } = process.electronBinding('in_app_purchase');
// inAppPurchase is an EventEmitter.
Object.setPrototypeOf(InAppPurchase.prototype, EventEmitter.prototype);
EventEmitter.call(inAppPurchase);
module.exports = inAppPurchase;
_inAppPurchase = inAppPurchase;
} else {
module.exports = {
purchaseProduct: (productID, quantity, callback) => {
_inAppPurchase = new EventEmitter();
Object.assign(_inAppPurchase, {
purchaseProduct: () => {
throw new Error('The inAppPurchase module can only be used on macOS');
},
canMakePayments: () => false,
getReceiptURL: () => ''
};
});
}
export default _inAppPurchase;

View File

@@ -10,7 +10,8 @@ const roles = {
about: {
get label () {
return isLinux ? 'About' : `About ${app.name}`;
}
},
...(isWindows && { appMethod: 'showAboutPanel' })
},
close: {
label: isMac ? 'Close Window' : 'Close',

View File

@@ -1,47 +0,0 @@
'use strict';
// TODO: Figure out a way to not duplicate this information between here and module-list
// It is currently duplicated as module-list "require"s all the browser API file and the
// remote module in the renderer process depends on that file. As a result webpack
// includes all the browser API files in the renderer process as well and we want to avoid that
const features = process.electronBinding('features');
// Browser side modules, please sort alphabetically.
module.exports = [
{ name: 'app' },
{ name: 'autoUpdater' },
{ name: 'BrowserView' },
{ name: 'BrowserWindow' },
{ name: 'contentTracing' },
{ name: 'crashReporter' },
{ name: 'dialog' },
{ name: 'globalShortcut' },
{ name: 'ipcMain' },
{ name: 'inAppPurchase' },
{ name: 'Menu' },
{ name: 'MenuItem' },
{ name: 'nativeTheme' },
{ name: 'net' },
{ name: 'netLog' },
{ name: 'MessageChannelMain' },
{ name: 'Notification' },
{ name: 'powerMonitor' },
{ name: 'powerSaveBlocker' },
{ name: 'protocol' },
{ name: 'screen' },
{ name: 'session' },
{ name: 'systemPreferences' },
{ name: 'TopLevelWindow' },
{ name: 'TouchBar' },
{ name: 'Tray' },
{ name: 'View' },
{ name: 'webContents' },
{ name: 'WebContentsView' }
];
if (features.isViewApiEnabled()) {
module.exports.push(
{ name: 'ImageView' }
);
}

View File

@@ -1,7 +1,5 @@
// TODO: Updating this file also required updating the module-keys file
const features = process.electronBinding('features');
// Browser side modules, please sort alphabetically.
export const browserModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'app', loader: () => require('./app') },
@@ -35,7 +33,13 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'WebContentsView', loader: () => require('./web-contents-view') }
];
if (features.isViewApiEnabled()) {
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

@@ -0,0 +1,47 @@
// TODO: Figure out a way to not duplicate this information between here and module-list
// It is currently duplicated as module-list "require"s all the browser API file and the
// remote module in the renderer process depends on that file. As a result webpack
// includes all the browser API files in the renderer process as well and we want to avoid that
// Browser side modules, please sort alphabetically.
export const browserModuleNames = [
'app',
'autoUpdater',
'BrowserView',
'BrowserWindow',
'contentTracing',
'crashReporter',
'dialog',
'globalShortcut',
'ipcMain',
'inAppPurchase',
'Menu',
'MenuItem',
'nativeTheme',
'net',
'netLog',
'MessageChannelMain',
'Notification',
'powerMonitor',
'powerSaveBlocker',
'protocol',
'screen',
'session',
'systemPreferences',
'TopLevelWindow',
'TouchBar',
'Tray',
'View',
'webContents',
'WebContentsView'
];
if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
browserModuleNames.push('desktopCapturer');
}
if (BUILDFLAG(ENABLE_VIEWS_API)) {
browserModuleNames.push(
'ImageView'
);
}

View File

@@ -1,10 +1,7 @@
'use strict';
const url = require('url');
const { EventEmitter } = require('events');
const { Readable, Writable } = require('stream');
const { app } = require('electron');
const { Session } = process.electronBinding('session');
import * as url from 'url';
import { Readable, Writable } from 'stream';
import { app } from 'electron';
import { ClientRequestConstructorOptions, UploadProgress } from 'electron/main';
const { net, Net, isValidHeaderName, isValidHeaderValue, createURLLoader } = process.electronBinding('net');
const kSupportedProtocols = new Set(['http:', 'https:']);
@@ -33,7 +30,11 @@ const discardableDuplicateHeaders = new Set([
]);
class IncomingMessage extends Readable {
constructor (responseHead) {
_shouldPush: boolean;
_data: (Buffer | null)[];
_responseHead: NodeJS.ResponseHead;
constructor (responseHead: NodeJS.ResponseHead) {
super();
this._shouldPush = false;
this._data = [];
@@ -49,7 +50,7 @@ class IncomingMessage extends Readable {
}
get headers () {
const filteredHeaders = {};
const filteredHeaders: Record<string, string | string[]> = {};
const { rawHeaders } = this._responseHead;
rawHeaders.forEach(header => {
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key) &&
@@ -60,7 +61,7 @@ class IncomingMessage extends Readable {
// keep set-cookie as an array per Node.js rules
// see https://nodejs.org/api/http.html#http_message_headers
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
filteredHeaders[header.key].push(header.value);
(filteredHeaders[header.key] as string[]).push(header.value);
} else {
filteredHeaders[header.key] = [header.value];
}
@@ -97,7 +98,7 @@ class IncomingMessage extends Readable {
throw new Error('HTTP trailers are not supported');
}
_storeInternalData (chunk) {
_storeInternalData (chunk: Buffer | null) {
this._data.push(chunk);
this._pushInternalData();
}
@@ -117,12 +118,13 @@ class IncomingMessage extends Readable {
/** Writable stream that buffers up everything written to it. */
class SlurpStream extends Writable {
_data: Buffer;
constructor () {
super();
this._data = Buffer.alloc(0);
}
_write (chunk, encoding, callback) {
_write (chunk: Buffer, encoding: string, callback: () => void) {
this._data = Buffer.concat([this._data, chunk]);
callback();
}
@@ -130,12 +132,17 @@ class SlurpStream extends Writable {
}
class ChunkedBodyStream extends Writable {
constructor (clientRequest) {
_pendingChunk: Buffer | undefined;
_downstream?: NodeJS.DataPipe;
_pendingCallback?: (error?: Error) => void;
_clientRequest: ClientRequest;
constructor (clientRequest: ClientRequest) {
super();
this._clientRequest = clientRequest;
}
_write (chunk, encoding, callback) {
_write (chunk: Buffer, encoding: string, callback: () => void) {
if (this._downstream) {
this._downstream.write(chunk).then(callback, callback);
} else {
@@ -149,40 +156,37 @@ class ChunkedBodyStream extends Writable {
}
}
_final (callback) {
this._downstream.done();
_final (callback: () => void) {
this._downstream!.done();
callback();
}
startReading (pipe) {
startReading (pipe: NodeJS.DataPipe) {
if (this._downstream) {
throw new Error('two startReading calls???');
}
this._downstream = pipe;
if (this._pendingChunk) {
const doneWriting = (maybeError) => {
const cb = this._pendingCallback;
const doneWriting = (maybeError: Error | void) => {
const cb = this._pendingCallback!;
delete this._pendingCallback;
delete this._pendingChunk;
cb(maybeError);
cb(maybeError || undefined);
};
this._downstream.write(this._pendingChunk).then(doneWriting, doneWriting);
}
}
}
function parseOptions (options) {
if (typeof options === 'string') {
options = url.parse(options);
} else {
options = { ...options };
}
type RedirectPolicy = 'manual' | 'follow' | 'error';
const method = (options.method || 'GET').toUpperCase();
let urlStr = options.url;
function parseOptions (optionsIn: ClientRequestConstructorOptions | string): NodeJS.CreateURLLoaderOptions & { redirectPolicy: RedirectPolicy, extraHeaders: Record<string, string> } {
const options: any = typeof optionsIn === 'string' ? url.parse(optionsIn) : { ...optionsIn };
let urlStr: string = options.url;
if (!urlStr) {
const urlObj = {};
const urlObj: url.UrlObject = {};
const protocol = options.protocol || 'http:';
if (!kSupportedProtocols.has(protocol)) {
throw new Error('Protocol "' + protocol + '" not supported');
@@ -228,14 +232,15 @@ function parseOptions (options) {
throw new TypeError('headers must be an object');
}
const urlLoaderOptions = {
method: method,
const urlLoaderOptions: NodeJS.CreateURLLoaderOptions & { redirectPolicy: RedirectPolicy, extraHeaders: Record<string, string | string[]> } = {
method: (options.method || 'GET').toUpperCase(),
url: urlStr,
redirectPolicy,
extraHeaders: options.headers || {},
body: null as any,
useSessionCookies: options.useSessionCookies || false
};
for (const [name, value] of Object.entries(urlLoaderOptions.extraHeaders)) {
for (const [name, value] of Object.entries(urlLoaderOptions.extraHeaders!)) {
if (!isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${name}'`);
}
@@ -244,7 +249,8 @@ function parseOptions (options) {
}
}
if (options.session) {
if (options.session instanceof Session) {
// Weak check, but it should be enough to catch 99% of accidental misuses.
if (options.session.constructor && options.session.constructor.name === 'Session') {
urlLoaderOptions.session = options.session;
} else {
throw new TypeError('`session` should be an instance of the Session class');
@@ -259,8 +265,20 @@ function parseOptions (options) {
return urlLoaderOptions;
}
class ClientRequest extends Writable {
constructor (options, callback) {
class ClientRequest extends Writable implements Electron.ClientRequest {
_started: boolean = false;
_firstWrite: boolean = false;
_aborted: boolean = false;
_chunkedEncoding: boolean | undefined;
_body: Writable | undefined;
_urlLoaderOptions: NodeJS.CreateURLLoaderOptions & { extraHeaders: Record<string, string> };
_redirectPolicy: RedirectPolicy;
_followRedirectCb?: () => void;
_uploadProgress?: { active: boolean, started: boolean, current: number, total: number };
_urlLoader?: NodeJS.URLLoader;
_response?: IncomingMessage;
constructor (options: ClientRequestConstructorOptions | string, callback?: (message: IncomingMessage) => void) {
super({ autoDestroy: true });
if (!app.isReady()) {
@@ -274,10 +292,9 @@ class ClientRequest extends Writable {
const { redirectPolicy, ...urlLoaderOptions } = parseOptions(options);
this._urlLoaderOptions = urlLoaderOptions;
this._redirectPolicy = redirectPolicy;
this._started = false;
}
set chunkedEncoding (value) {
set chunkedEncoding (value: boolean) {
if (this._started) {
throw new Error('chunkedEncoding can only be set before the request is started');
}
@@ -287,13 +304,13 @@ class ClientRequest extends Writable {
this._chunkedEncoding = !!value;
if (this._chunkedEncoding) {
this._body = new ChunkedBodyStream(this);
this._urlLoaderOptions.body = (pipe) => {
this._body.startReading(pipe);
this._urlLoaderOptions.body = (pipe: NodeJS.DataPipe) => {
(this._body! as ChunkedBodyStream).startReading(pipe);
};
}
}
setHeader (name, value) {
setHeader (name: string, value: string) {
if (typeof name !== 'string') {
throw new TypeError('`name` should be a string in setHeader(name, value)');
}
@@ -314,7 +331,7 @@ class ClientRequest extends Writable {
this._urlLoaderOptions.extraHeaders[key] = value;
}
getHeader (name) {
getHeader (name: string) {
if (name == null) {
throw new Error('`name` is required for getHeader(name)');
}
@@ -323,7 +340,7 @@ class ClientRequest extends Writable {
return this._urlLoaderOptions.extraHeaders[key];
}
removeHeader (name) {
removeHeader (name: string) {
if (name == null) {
throw new Error('`name` is required for removeHeader(name)');
}
@@ -336,12 +353,12 @@ class ClientRequest extends Writable {
delete this._urlLoaderOptions.extraHeaders[key];
}
_write (chunk, encoding, callback) {
_write (chunk: Buffer, encoding: string, callback: () => void) {
this._firstWrite = true;
if (!this._body) {
this._body = new SlurpStream();
this._body.on('finish', () => {
this._urlLoaderOptions.body = this._body.data();
this._urlLoaderOptions.body = (this._body as SlurpStream).data();
this._startRequest();
});
}
@@ -349,7 +366,7 @@ class ClientRequest extends Writable {
this._body.write(chunk, encoding, callback);
}
_final (callback) {
_final (callback: () => void) {
if (this._body) {
// TODO: is this the right way to forward to another stream?
this._body.end(callback);
@@ -362,13 +379,14 @@ class ClientRequest extends Writable {
_startRequest () {
this._started = true;
const stringifyValues = (obj) => {
const ret = {};
const stringifyValues = (obj: Record<string, any>) => {
const ret: Record<string, string> = {};
for (const k of Object.keys(obj)) {
ret[k] = obj[k].toString();
}
return ret;
};
this._urlLoaderOptions.referrer = this._urlLoaderOptions.extraHeaders.referer || '';
const opts = { ...this._urlLoaderOptions, extraHeaders: stringifyValues(this._urlLoaderOptions.extraHeaders) };
this._urlLoader = createURLLoader(opts);
this._urlLoader.on('response-started', (event, finalUrl, responseHead) => {
@@ -376,7 +394,7 @@ class ClientRequest extends Writable {
this.emit('response', response);
});
this._urlLoader.on('data', (event, data) => {
this._response._storeInternalData(Buffer.from(data));
this._response!._storeInternalData(Buffer.from(data));
});
this._urlLoader.on('complete', () => {
if (this._response) { this._response._storeInternalData(null); }
@@ -405,7 +423,7 @@ class ClientRequest extends Writable {
try {
this.emit('redirect', statusCode, newMethod, newUrl, headers);
} finally {
this._followRedirectCb = null;
this._followRedirectCb = undefined;
if (!_followRedirect && !this._aborted) {
this._die(new Error('Redirect was cancelled'));
}
@@ -418,7 +436,7 @@ class ClientRequest extends Writable {
this._followRedirectCb = () => {};
this.emit('redirect', statusCode, newMethod, newUrl, headers);
} finally {
this._followRedirectCb = null;
this._followRedirectCb = undefined;
}
} else {
this._die(new Error(`Unexpected redirect policy '${this._redirectPolicy}'`));
@@ -453,7 +471,7 @@ class ClientRequest extends Writable {
this._die();
}
_die (err) {
_die (err?: Error) {
this.destroy(err);
if (this._urlLoader) {
this._urlLoader.cancel();
@@ -461,12 +479,12 @@ class ClientRequest extends Writable {
}
}
getUploadProgress () {
return this._uploadProgress ? { ...this._uploadProgress } : { active: false };
getUploadProgress (): UploadProgress {
return this._uploadProgress ? { ...this._uploadProgress } : { active: false, started: false, current: 0, total: 0 };
}
}
Net.prototype.request = function (options, callback) {
Net.prototype.request = function (options: ClientRequestConstructorOptions | string, callback?: (message: IncomingMessage) => void) {
return new ClientRequest(options, callback);
};

View File

@@ -1,7 +0,0 @@
'use strict';
const { Notification, isSupported } = process.electronBinding('notification');
Notification.isSupported = isSupported;
module.exports = Notification;

View File

@@ -0,0 +1,5 @@
const { Notification: ElectronNotification, isSupported } = process.electronBinding('notification');
ElectronNotification.isSupported = isSupported;
export default ElectronNotification;

View File

@@ -1,3 +0,0 @@
'use strict';
module.exports = process.electronBinding('power_save_blocker').powerSaveBlocker;

View File

@@ -0,0 +1 @@
export default process.electronBinding('power_save_blocker').powerSaveBlocker;

View File

@@ -1,23 +0,0 @@
'use strict';
const { EventEmitter } = require('events');
const { app, deprecate } = require('electron');
const { fromPartition, Session } = process.electronBinding('session');
// Public API.
Object.defineProperties(exports, {
defaultSession: {
enumerable: true,
get () { return fromPartition(''); }
},
fromPartition: {
enumerable: true,
value: fromPartition
}
});
Object.setPrototypeOf(Session.prototype, EventEmitter.prototype);
Session.prototype._init = function () {
app.emit('session-created', this);
};

View File

@@ -0,0 +1,8 @@
const { fromPartition } = process.electronBinding('session');
export default {
fromPartition,
get defaultSession () {
return fromPartition('');
}
};

View File

@@ -1,5 +1,3 @@
'use strict';
const { Tray } = process.electronBinding('tray');
module.exports = Tray;
export default Tray;

View File

@@ -1,5 +1,3 @@
'use strict';
const { View } = process.electronBinding('view');
module.exports = View;
export default View;

View File

@@ -1,8 +1,7 @@
const electron = require('electron');
import { View } from 'electron';
const { View } = electron;
const { ImageView } = process.electronBinding('image_view');
Object.setPrototypeOf(ImageView.prototype, View.prototype);
module.exports = ImageView;
export default ImageView;

View File

@@ -1,10 +1,7 @@
'use strict';
import { View } from 'electron';
const electron = require('electron');
const { View } = electron;
const { WebContentsView } = process.electronBinding('web_contents_view');
Object.setPrototypeOf(WebContentsView.prototype, View.prototype);
module.exports = WebContentsView;
export default WebContentsView;

View File

@@ -1,6 +1,5 @@
'use strict';
const features = process.electronBinding('features');
const { EventEmitter } = require('events');
const electron = require('electron');
const path = require('path');
@@ -341,7 +340,7 @@ WebContents.prototype.printToPDF = function (options) {
printSettings.scaleFactor = Math.ceil(printSettings.scaleFactor) % 100;
// PrinterType enum from //printing/print_job_constants.h
printSettings.printerType = 2;
if (features.isPrintingEnabled()) {
if (this._printToPDF) {
return this._printToPDF(printSettings);
} else {
const error = new Error('Printing feature is disabled');
@@ -375,7 +374,7 @@ WebContents.prototype.print = function (options = {}, callback) {
}
}
if (features.isPrintingEnabled()) {
if (this._print) {
if (callback) {
this._print(options, callback);
} else {
@@ -387,7 +386,7 @@ WebContents.prototype.print = function (options = {}, callback) {
};
WebContents.prototype.getPrinters = function () {
if (features.isPrintingEnabled()) {
if (this._getPrinters) {
return this._getPrinters();
} else {
console.error('Error: Printing feature is disabled.');
@@ -502,6 +501,10 @@ WebContents.prototype._init = function () {
app.emit('renderer-process-crashed', event, this, ...args);
});
this.on('render-process-gone', (event, ...args) => {
app.emit('render-process-gone', event, this, ...args);
});
// The devtools requests the webContents to reload.
this.on('devtools-reload-page', function () {
this.reload();
@@ -588,6 +591,11 @@ WebContents.prototype._init = function () {
get: () => this.getFrameRate(),
set: (rate) => this.setFrameRate(rate)
});
Object.defineProperty(this, 'backgroundThrottling', {
get: () => this.getBackgroundThrottling(),
set: (allowed) => this.setBackgroundThrottling(allowed)
});
};
// Public APIs.

View File

@@ -1,25 +0,0 @@
'use strict';
const { app } = require('electron');
const path = require('path');
const getTempDirectory = function () {
try {
return app.getPath('temp');
} catch {
// Delibrately laze-load the os module, this file is on the hot
// path when booting Electron and os takes between 5 - 8ms to load and we do not need it yet
return require('os').tmpdir();
}
};
exports.crashReporterInit = function (options) {
const productName = options.productName || app.name;
const crashesDirectory = path.join(getTempDirectory(), `${productName} Crashes`);
return {
productName,
crashesDirectory,
appVersion: app.getVersion()
};
};

View File

@@ -1,4 +1,4 @@
const { createDesktopCapturer } = process.electronBinding('desktop_capturer');
const { createDesktopCapturer, getMediaSourceIdForWebContents: getMediaSourceIdForWebContentsBinding } = process.electronBinding('desktop_capturer');
const deepEqual = (a: ElectronInternal.GetSourcesOptions, b: ElectronInternal.GetSourcesOptions) => JSON.stringify(a) === JSON.stringify(b);
@@ -7,7 +7,28 @@ let currentlyRunning: {
getSources: Promise<ElectronInternal.GetSourcesResult[]>;
}[] = [];
export const getSources = (event: Electron.IpcMainEvent, options: ElectronInternal.GetSourcesOptions) => {
// |options.types| can't be empty and must be an array
function isValid (options: Electron.SourcesOptions) {
const types = options ? options.types : undefined;
return Array.isArray(types);
}
export const getSourcesImpl = (event: Electron.IpcMainEvent | null, args: Electron.SourcesOptions) => {
if (!isValid(args)) throw new Error('Invalid options');
const captureWindow = args.types.includes('window');
const captureScreen = args.types.includes('screen');
const { thumbnailSize = { width: 150, height: 150 } } = args;
const { fetchWindowIcons = false } = args;
const options = {
captureWindow,
captureScreen,
thumbnailSize,
fetchWindowIcons
};
for (const running of currentlyRunning) {
if (deepEqual(running.options, options)) {
// If a request is currently running for the same options
@@ -34,23 +55,19 @@ export const getSources = (event: Electron.IpcMainEvent, options: ElectronIntern
reject(error);
};
capturer._onfinished = (sources: Electron.DesktopCapturerSource[], fetchWindowIcons: boolean) => {
capturer._onfinished = (sources: Electron.DesktopCapturerSource[]) => {
stopRunning();
resolve(sources.map(source => ({
id: source.id,
name: source.name,
thumbnail: source.thumbnail.toDataURL(),
display_id: source.display_id,
appIcon: (fetchWindowIcons && source.appIcon) ? source.appIcon.toDataURL() : null
})));
resolve(sources);
};
capturer.startHandling(options.captureWindow, options.captureScreen, options.thumbnailSize, options.fetchWindowIcons);
capturer.startHandling(captureWindow, captureScreen, thumbnailSize, fetchWindowIcons);
// If the WebContents is destroyed before receiving result, just remove the
// reference to emit and the capturer itself so that it never dispatches
// back to the renderer
event.sender.once('destroyed', () => stopRunning());
if (event) {
event.sender.once('destroyed', () => stopRunning());
}
});
currentlyRunning.push({
@@ -60,3 +77,7 @@ export const getSources = (event: Electron.IpcMainEvent, options: ElectronIntern
return getSources;
};
export const getMediaSourceIdForWebContents = (event: Electron.IpcMainEvent, webContentsId: number) => {
return getMediaSourceIdForWebContentsBinding(event.sender.id, webContentsId);
};

View File

@@ -32,6 +32,7 @@ const supportedWebViewEvents = [
'focus-change',
'close',
'crashed',
'render-process-gone',
'plugin-crashed',
'destroyed',
'page-title-updated',
@@ -217,7 +218,8 @@ const attachGuest = function (event, embedderFrameId, elementInstanceId, guestIn
['nodeIntegration', false],
['enableRemoteModule', false],
['sandbox', true],
['nodeIntegrationInSubFrames', false]
['nodeIntegrationInSubFrames', false],
['enableWebSQL', false]
]);
// Inherit certain option values from embedder

View File

@@ -19,7 +19,8 @@ const inheritedWebPreferences = new Map([
['enableRemoteModule', false],
['sandbox', true],
['webviewTag', false],
['nodeIntegrationInSubFrames', false]
['nodeIntegrationInSubFrames', false],
['enableWebSQL', false]
]);
// Copy attribute of |parent| to |child| if it is not defined in |child|.

View File

@@ -157,12 +157,10 @@ app._setDefaultAppPaths(packagePath);
// Load the chrome devtools support.
require('@electron/internal/browser/devtools');
const features = process.electronBinding('features');
// Load the chrome extension support.
require('@electron/internal/browser/chrome-extension-shim');
if (features.isRemoteModuleEnabled()) {
if (BUILDFLAG(ENABLE_REMOTE_MODULE)) {
require('@electron/internal/browser/remote/server');
}
@@ -188,6 +186,7 @@ function currentPlatformSupportsAppIndicator () {
}
// Workaround for electron/electron#5050 and electron/electron#9046
process.env.ORIGINAL_XDG_CURRENT_DESKTOP = process.env.XDG_CURRENT_DESKTOP;
if (currentPlatformSupportsAppIndicator()) {
process.env.XDG_CURRENT_DESKTOP = 'Unity';
}

View File

@@ -4,11 +4,13 @@ import * as electron from 'electron';
import { EventEmitter } from 'events';
import objectsRegistry from './objects-registry';
import { ipcMainInternal } from '../ipc-main-internal';
import { isPromise, isSerializableObject } from '@electron/internal/common/type-utils';
import { isPromise, isSerializableObject, deserialize, serialize } from '@electron/internal/common/type-utils';
import { Size } from 'electron/main';
const v8Util = process.electronBinding('v8_util');
const eventBinding = process.electronBinding('event');
const features = process.electronBinding('features');
const { NativeImage } = process.electronBinding('native_image');
if (!features.isRemoteModuleEnabled()) {
throw new Error('remote module is disabled');
@@ -113,6 +115,9 @@ type MetaType = {
} | {
type: 'promise',
then: MetaType
} | {
type: 'nativeimage'
value: electron.NativeImage
}
// Convert a real value into meta data.
@@ -123,6 +128,8 @@ const valueToMeta = function (sender: electron.WebContents, contextId: string, v
// Recognize certain types of objects.
if (value instanceof Buffer) {
type = 'buffer';
} else if (value instanceof NativeImage) {
type = 'nativeimage';
} else if (Array.isArray(value)) {
type = 'array';
} else if (value instanceof Error) {
@@ -146,6 +153,8 @@ const valueToMeta = function (sender: electron.WebContents, contextId: string, v
type,
members: value.map((el: any) => valueToMeta(sender, contextId, el, optimizeSimpleObject))
};
} else if (type === 'nativeimage') {
return { type, value: serialize(value) };
} else if (type === 'object' || type === 'function') {
return {
type,
@@ -233,7 +242,10 @@ type MetaTypeFromRenderer = {
} | {
type: 'object',
name: string,
members: { name: string, value: MetaTypeFromRenderer }[]
members: {
name: string,
value: MetaTypeFromRenderer
}[]
} | {
type: 'function-with-return-value',
value: MetaTypeFromRenderer
@@ -242,6 +254,14 @@ type MetaTypeFromRenderer = {
id: number,
location: string,
length: number
} | {
type: 'nativeimage',
value: {
size: Size,
buffer: Buffer,
scaleFactor: number,
dataURL: string
}[]
}
const fakeConstructor = (constructor: Function, name: string) =>
@@ -259,6 +279,8 @@ const fakeConstructor = (constructor: Function, name: string) =>
const unwrapArgs = function (sender: electron.WebContents, frameId: number, contextId: string, args: any[]) {
const metaToValue = function (meta: MetaTypeFromRenderer): any {
switch (meta.type) {
case 'nativeimage':
return deserialize(meta.value);
case 'value':
return meta.value;
case 'remote-object':

View File

@@ -5,9 +5,7 @@ const fs = require('fs');
const eventBinding = process.electronBinding('event');
const clipboard = process.electronBinding('clipboard');
const features = process.electronBinding('features');
const { crashReporterInit } = require('@electron/internal/browser/crash-reporter-init');
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal');
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils');
const guestViewManager = require('@electron/internal/browser/guest-view-manager');
@@ -37,10 +35,6 @@ ipcMainInternal.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event) {
event.returnValue = null;
});
ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_INIT', function (event, options) {
return crashReporterInit(options);
});
ipcMainInternal.handle('ELECTRON_BROWSER_GET_LAST_WEB_PREFERENCES', function (event) {
return event.sender.getLastWebPreferences();
});
@@ -65,10 +59,10 @@ ipcMainUtils.handleSync('ELECTRON_BROWSER_CLIPBOARD_SYNC', function (event, meth
return typeUtils.serialize(electron.clipboard[method](...typeUtils.deserialize(args)));
});
if (features.isDesktopCapturerEnabled()) {
if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
const desktopCapturer = require('@electron/internal/browser/desktop-capturer');
ipcMainInternal.handle('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', function (event, options, stack) {
ipcMainInternal.handle('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', async function (event, options, stack) {
logStack(event.sender, 'desktopCapturer.getSources()', stack);
const customEvent = emitCustomEvent(event.sender, 'desktop-capturer-get-sources');
@@ -77,11 +71,15 @@ if (features.isDesktopCapturerEnabled()) {
return [];
}
return desktopCapturer.getSources(event, options);
return typeUtils.serialize(await desktopCapturer.getSourcesImpl(event, options));
});
ipcMainInternal.handle('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_MEDIA_SOURCE_ID_FOR_WEB_CONTENTS', function (event, webContentsId, stack) {
return desktopCapturer.getMediaSourceIdForWebContents(event, webContentsId);
});
}
const isRemoteModuleEnabled = features.isRemoteModuleEnabled()
const isRemoteModuleEnabled = BUILDFLAG(ENABLE_REMOTE_MODULE)
? require('@electron/internal/browser/remote/server').isRemoteModuleEnabled
: () => false;
@@ -120,3 +118,23 @@ ipcMainUtils.handleSync('ELECTRON_BROWSER_SANDBOX_LOAD', async function (event)
ipcMainInternal.on('ELECTRON_BROWSER_PRELOAD_ERROR', function (event, preloadPath, error) {
event.sender.emit('preload-error', event, preloadPath, error);
});
ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_GET_LAST_CRASH_REPORT', () => {
return electron.crashReporter.getLastCrashReport();
});
ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_GET_UPLOADED_REPORTS', () => {
return electron.crashReporter.getUploadedReports();
});
ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_GET_UPLOAD_TO_SERVER', () => {
return electron.crashReporter.getUploadToServer();
});
ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_SET_UPLOAD_TO_SERVER', (event, uploadToServer) => {
return electron.crashReporter.setUploadToServer(uploadToServer);
});
ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_GET_CRASHES_DIRECTORY', () => {
return electron.crashReporter.getCrashesDirectory();
});

View File

@@ -1,13 +1,11 @@
'use strict';
const clipboard = process.electronBinding('clipboard');
if (process.type === 'renderer') {
const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils');
const typeUtils = require('@electron/internal/common/type-utils');
const makeRemoteMethod = function (method) {
return (...args) => {
const makeRemoteMethod = function (method: keyof Electron.Clipboard) {
return (...args: any[]) => {
args = typeUtils.serialize(args);
const result = ipcRendererUtils.invokeSync('ELECTRON_BROWSER_CLIPBOARD_SYNC', method, ...args);
return typeUtils.deserialize(result);
@@ -16,7 +14,7 @@ if (process.type === 'renderer') {
if (process.platform === 'linux') {
// On Linux we could not access clipboard in renderer process.
for (const method of Object.keys(clipboard)) {
for (const method of Object.keys(clipboard) as (keyof Electron.Clipboard)[]) {
clipboard[method] = makeRemoteMethod(method);
}
} else if (process.platform === 'darwin') {
@@ -26,4 +24,4 @@ if (process.type === 'renderer') {
}
}
module.exports = clipboard;
export default clipboard;

View File

@@ -1,5 +1,3 @@
'use strict';
const { nativeImage } = process.electronBinding('native_image');
module.exports = nativeImage;
export default nativeImage;

View File

@@ -1,3 +0,0 @@
'use strict';
module.exports = process.electronBinding('shell');

1
lib/common/api/shell.ts Normal file
View File

@@ -0,0 +1 @@
export default process.electronBinding('shell');

View File

@@ -23,6 +23,7 @@ const serializableTypes = [
ArrayBuffer
];
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#Supported_types
export function isSerializableObject (value: any) {
return value === null || ArrayBuffer.isView(value) || serializableTypes.some(type => value instanceof type);
}
@@ -33,14 +34,55 @@ const objectMap = function (source: Object, mapper: (value: any) => any) {
return Object.fromEntries(targetEntries);
};
function serializeNativeImage (image: any) {
const representations = [];
const scaleFactors = image.getScaleFactors();
// Use Buffer when there's only one representation for better perf.
// This avoids compressing to/from PNG where it's not necessary to
// ensure uniqueness of dataURLs (since there's only one).
if (scaleFactors.length === 1) {
const scaleFactor = scaleFactors[0];
const size = image.getSize(scaleFactor);
const buffer = image.toBitmap({ scaleFactor });
representations.push({ scaleFactor, size, buffer });
} else {
// Construct from dataURLs to ensure that they are not lost in creation.
for (const scaleFactor of scaleFactors) {
const size = image.getSize(scaleFactor);
const dataURL = image.toDataURL({ scaleFactor });
representations.push({ scaleFactor, size, dataURL });
}
}
return { __ELECTRON_SERIALIZED_NativeImage__: true, representations };
}
function deserializeNativeImage (value: any) {
const image = nativeImage.createEmpty();
// Use Buffer when there's only one representation for better perf.
// This avoids compressing to/from PNG where it's not necessary to
// ensure uniqueness of dataURLs (since there's only one).
if (value.representations.length === 1) {
const { buffer, size, scaleFactor } = value.representations[0];
const { width, height } = size;
image.addRepresentation({ buffer, scaleFactor, width, height });
} else {
// Construct from dataURLs to ensure that they are not lost in creation.
for (const rep of value.representations) {
const { dataURL, size, scaleFactor } = rep;
const { width, height } = size;
image.addRepresentation({ dataURL, scaleFactor, width, height });
}
}
return image;
}
export function serialize (value: any): any {
if (value instanceof NativeImage) {
return {
buffer: value.toBitmap(),
size: value.getSize(),
__ELECTRON_SERIALIZED_NativeImage__: true
};
} else if (Array.isArray(value)) {
return serializeNativeImage(value);
} if (Array.isArray(value)) {
return value.map(serialize);
} else if (isSerializableObject(value)) {
return value;
@@ -53,7 +95,7 @@ export function serialize (value: any): any {
export function deserialize (value: any): any {
if (value && value.__ELECTRON_SERIALIZED_NativeImage__) {
return nativeImage.createFromBitmap(value.buffer, value.size);
return deserializeNativeImage(value);
} else if (Array.isArray(value)) {
return value.map(deserialize);
} else if (isSerializableObject(value)) {

View File

@@ -7,15 +7,12 @@ const checkContextIsolationEnabled = () => {
if (!contextIsolationEnabled) throw new Error('contextBridge API can only be used when contextIsolation is enabled');
};
const contextBridge = {
const contextBridge: Electron.ContextBridge = {
exposeInMainWorld: (key: string, api: Record<string, any>) => {
checkContextIsolationEnabled();
return binding.exposeAPIInMainWorld(key, api);
},
debugGC: () => binding._debugGCMaps({})
};
if (!binding._debugGCMaps) delete contextBridge.debugGC;
}
} as any;
export default contextBridge;
@@ -32,3 +29,7 @@ export const internalContextBridge = {
},
isInMainWorld: () => binding._isCalledFromMainWorld() as boolean
};
if (binding._isDebug) {
contextBridge.internalContextBridge = internalContextBridge;
}

View File

@@ -1,12 +0,0 @@
'use strict';
const CrashReporter = require('@electron/internal/common/crash-reporter');
const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils');
class CrashReporterRenderer extends CrashReporter {
init (options) {
return ipcRendererUtils.invokeSync('ELECTRON_CRASH_REPORTER_INIT', options);
}
}
module.exports = new CrashReporterRenderer();

View File

@@ -0,0 +1,50 @@
import { invokeSync } from '../ipc-renderer-internal-utils';
import { deprecate } from 'electron';
const binding = process.electronBinding('crash_reporter');
export default {
start (options: Electron.CrashReporterStartOptions) {
deprecate.log('crashReporter.start is deprecated in the renderer process. Call it from the main process instead.');
for (const [k, v] of Object.entries(options.extra || {})) {
binding.addExtraParameter(k, String(v));
}
},
getLastCrashReport (): Electron.CrashReport | null {
deprecate.log('crashReporter.getLastCrashReport is deprecated in the renderer process. Call it from the main process instead.');
return invokeSync('ELECTRON_CRASH_REPORTER_GET_LAST_CRASH_REPORT');
},
getUploadedReports () {
deprecate.log('crashReporter.getUploadedReports is deprecated in the renderer process. Call it from the main process instead.');
return invokeSync('ELECTRON_CRASH_REPORTER_GET_UPLOADED_REPORTS');
},
getUploadToServer () {
deprecate.log('crashReporter.getUploadToServer is deprecated in the renderer process. Call it from the main process instead.');
return invokeSync('ELECTRON_CRASH_REPORTER_GET_UPLOAD_TO_SERVER');
},
setUploadToServer (uploadToServer: boolean) {
deprecate.log('crashReporter.setUploadToServer is deprecated in the renderer process. Call it from the main process instead.');
return invokeSync('ELECTRON_CRASH_REPORTER_SET_UPLOAD_TO_SERVER', uploadToServer);
},
getCrashesDirectory () {
deprecate.log('crashReporter.getCrashesDirectory is deprecated in the renderer process. Call it from the main process instead.');
return invokeSync('ELECTRON_CRASH_REPORTER_GET_CRASHES_DIRECTORY');
},
addExtraParameter (key: string, value: string) {
binding.addExtraParameter(key, value);
},
removeExtraParameter (key: string) {
binding.removeExtraParameter(key);
},
getParameters () {
return binding.getParameters();
}
};

View File

@@ -1,14 +1,8 @@
import { nativeImage } from 'electron';
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
import { deserialize } from '@electron/internal/common/type-utils';
const { hasSwitch } = process.electronBinding('command_line');
// |options.types| can't be empty and must be an array
function isValid (options: Electron.SourcesOptions) {
const types = options ? options.types : undefined;
return Array.isArray(types);
}
const enableStacks = hasSwitch('enable-api-filtering-logging');
function getCurrentStack () {
@@ -20,26 +14,9 @@ function getCurrentStack () {
}
export async function getSources (options: Electron.SourcesOptions) {
if (!isValid(options)) throw new Error('Invalid options');
const captureWindow = options.types.includes('window');
const captureScreen = options.types.includes('screen');
const { thumbnailSize = { width: 150, height: 150 } } = options;
const { fetchWindowIcons = false } = options;
const sources = await ipcRendererInternal.invoke<ElectronInternal.GetSourcesResult[]>('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', {
captureWindow,
captureScreen,
thumbnailSize,
fetchWindowIcons
} as ElectronInternal.GetSourcesOptions, getCurrentStack());
return sources.map(source => ({
id: source.id,
name: source.name,
thumbnail: nativeImage.createFromDataURL(source.thumbnail),
display_id: source.display_id,
appIcon: source.appIcon ? nativeImage.createFromDataURL(source.appIcon) : null
}));
return deserialize(await ipcRendererInternal.invoke('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', options, getCurrentStack()));
}
export function getMediaSourceIdForWebContents (webContentsId: number) {
return ipcRendererInternal.invoke<string>('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_MEDIA_SOURCE_ID_FOR_WEB_CONTENTS', webContentsId, getCurrentStack());
}

View File

@@ -1,39 +1,36 @@
const { ipc } = process.electronBinding('ipc');
const v8Util = process.electronBinding('v8_util');
import { EventEmitter } from 'events';
const { ipc } = process.electronBinding('ipc');
// Created by init.js.
const ipcRenderer = v8Util.getHiddenValue<Electron.IpcRenderer>(global, 'ipc');
const internal = false;
// TODO(MarshallOfSound): Remove if statement when isolated_bundle and content_script_bundle are gone
if (!ipcRenderer.send) {
ipcRenderer.send = function (channel, ...args) {
return ipc.send(internal, channel, args);
};
const ipcRenderer = new EventEmitter() as Electron.IpcRenderer;
ipcRenderer.send = function (channel, ...args) {
return ipc.send(internal, channel, args);
};
ipcRenderer.sendSync = function (channel, ...args) {
return ipc.sendSync(internal, channel, args)[0];
};
ipcRenderer.sendSync = function (channel, ...args) {
return ipc.sendSync(internal, channel, args)[0];
};
ipcRenderer.sendToHost = function (channel, ...args) {
return ipc.sendToHost(channel, args);
};
ipcRenderer.sendToHost = function (channel, ...args) {
return ipc.sendToHost(channel, args);
};
ipcRenderer.sendTo = function (webContentsId, channel, ...args) {
return ipc.sendTo(internal, false, webContentsId, channel, args);
};
ipcRenderer.sendTo = function (webContentsId, channel, ...args) {
return ipc.sendTo(internal, false, webContentsId, channel, args);
};
ipcRenderer.invoke = async function (channel, ...args) {
const { error, result } = await ipc.invoke(internal, channel, args);
if (error) {
throw new Error(`Error invoking remote method '${channel}': ${error}`);
}
return result;
};
ipcRenderer.invoke = async function (channel, ...args) {
const { error, result } = await ipc.invoke(internal, channel, args);
if (error) {
throw new Error(`Error invoking remote method '${channel}': ${error}`);
}
return result;
};
ipcRenderer.postMessage = function (channel: string, message: any, transferables: any) {
return ipc.postMessage(channel, message, transferables);
};
}
ipcRenderer.postMessage = function (channel: string, message: any, transferables: any) {
return ipc.postMessage(channel, message, transferables);
};
export default ipcRenderer;

View File

@@ -1,4 +1,3 @@
const features = process.electronBinding('features');
const v8Util = process.electronBinding('v8_util');
const enableRemoteModule = v8Util.getHiddenValue<boolean>(global, 'enableRemoteModule');
@@ -11,10 +10,16 @@ export const rendererModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'webFrame', loader: () => require('./web-frame') }
];
if (features.isDesktopCapturerEnabled()) {
rendererModuleList.push({ name: 'desktopCapturer', loader: () => require('./desktop-capturer') });
if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
rendererModuleList.push({
name: 'desktopCapturer',
loader: () => require('@electron/internal/renderer/api/desktop-capturer')
});
}
if (features.isRemoteModuleEnabled() && enableRemoteModule) {
rendererModuleList.push({ name: 'remote', loader: () => require('./remote') });
if (BUILDFLAG(ENABLE_REMOTE_MODULE) && enableRemoteModule) {
rendererModuleList.push({
name: 'remote',
loader: () => require('@electron/internal/renderer/api/remote')
});
}

View File

@@ -2,9 +2,10 @@
const v8Util = process.electronBinding('v8_util');
const { hasSwitch } = process.electronBinding('command_line');
const { NativeImage } = process.electronBinding('native_image');
const { CallbacksRegistry } = require('@electron/internal/renderer/remote/callbacks-registry');
const { isPromise, isSerializableObject } = require('@electron/internal/common/type-utils');
const { isPromise, isSerializableObject, serialize, deserialize } = require('@electron/internal/common/type-utils');
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal');
const callbacksRegistry = new CallbacksRegistry();
@@ -35,7 +36,9 @@ function wrapArgs (args, visited = new Set()) {
};
}
if (Array.isArray(value)) {
if (value instanceof NativeImage) {
return { type: 'nativeimage', value: serialize(value) };
} else if (Array.isArray(value)) {
visited.add(value);
const meta = {
type: 'array',
@@ -216,6 +219,7 @@ function metaToValue (meta) {
const types = {
value: () => meta.value,
array: () => meta.members.map((member) => metaToValue(member)),
nativeimage: () => deserialize(meta.value),
buffer: () => Buffer.from(meta.value.buffer, meta.value.byteOffset, meta.value.byteLength),
promise: () => Promise.resolve({ then: metaToValue(meta.then) }),
error: () => metaToError(meta),
@@ -354,7 +358,9 @@ const addBuiltinProperty = (name) => {
};
const { commonModuleList } = require('@electron/internal/common/api/module-list');
const browserModules = commonModuleList.concat(require('@electron/internal/browser/api/module-keys'));
const { browserModuleNames } = require('@electron/internal/browser/api/module-names');
const browserModules = commonModuleList.concat(browserModuleNames.map(name => ({ name })));
// And add a helper receiver for each one.
browserModules

View File

@@ -1,4 +1,3 @@
import { EventEmitter } from 'events';
import * as path from 'path';
const Module = require('module');
@@ -39,20 +38,17 @@ require('@electron/internal/common/init');
// The global variable will be used by ipc for event dispatching
const v8Util = process.electronBinding('v8_util');
const ipcEmitter = new EventEmitter();
const ipcInternalEmitter = new EventEmitter();
v8Util.setHiddenValue(global, 'ipc', ipcEmitter);
v8Util.setHiddenValue(global, 'ipc-internal', ipcInternalEmitter);
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal');
const ipcRenderer = require('@electron/internal/renderer/api/ipc-renderer').default;
v8Util.setHiddenValue(global, 'ipcNative', {
onMessage (internal: boolean, channel: string, ports: any[], args: any[], senderId: number) {
const sender = internal ? ipcInternalEmitter : ipcEmitter;
const sender = internal ? ipcRendererInternal : ipcRenderer;
sender.emit(channel, { sender, senderId, ports }, ...args);
}
});
// Use electron module after everything is ready.
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal');
const { webFrameInit } = require('@electron/internal/renderer/web-frame-init');
webFrameInit();
@@ -84,9 +80,6 @@ const appPath = parseOption('app-path', null);
const guestInstanceId = parseOption('guest-instance-id', null, value => parseInt(value));
const openerId = parseOption('opener-id', null, value => parseInt(value));
// The arguments to be passed to isolated world.
const isolatedWorldArgs = { ipcRendererInternal, guestInstanceId, isHiddenPage, openerId, usesNativeWindowOpen, rendererProcessReuseEnabled };
// The webContents preload script is loaded after the session preload scripts.
if (preloadScript) {
preloadScripts.push(preloadScript);
@@ -116,11 +109,6 @@ if (process.isMainFrame) {
webViewInit(contextIsolation, webviewTag, guestInstanceId);
}
// Pass the arguments to isolatedWorld.
if (contextIsolation) {
v8Util.setHiddenValue(global, 'isolated-world-args', isolatedWorldArgs);
}
if (nodeIntegration) {
// Export node bindings to global.
const { makeRequireFunction } = __non_webpack_require__('internal/modules/cjs/helpers') // eslint-disable-line

View File

@@ -1,33 +1,32 @@
const { ipc } = process.electronBinding('ipc');
const v8Util = process.electronBinding('v8_util');
import { EventEmitter } from 'events';
const { ipc } = process.electronBinding('ipc');
// Created by init.js.
export const ipcRendererInternal = v8Util.getHiddenValue<Electron.IpcRendererInternal>(global, 'ipc-internal');
const internal = true;
// TODO(MarshallOfSound): Remove if statement when isolated_bundle and content_script_bundle are gone
if (!ipcRendererInternal.send) {
ipcRendererInternal.send = function (channel, ...args) {
return ipc.send(internal, channel, args);
};
const ipcRendererInternal = new EventEmitter() as any as Electron.IpcRendererInternal;
ipcRendererInternal.send = function (channel, ...args) {
return ipc.send(internal, channel, args);
};
ipcRendererInternal.sendSync = function (channel, ...args) {
return ipc.sendSync(internal, channel, args)[0];
};
ipcRendererInternal.sendSync = function (channel, ...args) {
return ipc.sendSync(internal, channel, args)[0];
};
ipcRendererInternal.sendTo = function (webContentsId, channel, ...args) {
return ipc.sendTo(internal, false, webContentsId, channel, args);
};
ipcRendererInternal.sendTo = function (webContentsId, channel, ...args) {
return ipc.sendTo(internal, false, webContentsId, channel, args);
};
ipcRendererInternal.sendToAll = function (webContentsId, channel, ...args) {
return ipc.sendTo(internal, true, webContentsId, channel, args);
};
ipcRendererInternal.sendToAll = function (webContentsId, channel, ...args) {
return ipc.sendTo(internal, true, webContentsId, channel, args);
};
ipcRendererInternal.invoke = async function<T> (channel: string, ...args: any[]) {
const { error, result } = await ipc.invoke<T>(internal, channel, args);
if (error) {
throw new Error(`Error invoking remote method '${channel}': ${error}`);
}
return result;
};
}
ipcRendererInternal.invoke = async function<T> (channel: string, ...args: any[]) {
const { error, result } = await ipc.invoke<T>(internal, channel, args);
if (error) {
throw new Error(`Error invoking remote method '${channel}': ${error}`);
}
return result;
};
export { ipcRendererInternal };

View File

@@ -125,7 +125,11 @@ class LocationProxy {
}
private getGuestURL (): URL | null {
const urlString = this._invokeWebContentsMethodSync('getURL') as string;
const maybeURL = this._invokeWebContentsMethodSync('getURL') as string;
// When there's no previous frame the url will be blank, so accountfor that here
// to prevent url parsing errors on an empty string.
const urlString = maybeURL !== '' ? maybeURL : 'about:blank';
try {
return new URL(urlString);
} catch (e) {

View File

@@ -1,5 +1,3 @@
const features = process.electronBinding('features');
export const moduleList: ElectronInternal.ModuleEntry[] = [
{
name: 'contextBridge',
@@ -29,14 +27,14 @@ export const moduleList: ElectronInternal.ModuleEntry[] = [
}
];
if (features.isDesktopCapturerEnabled()) {
if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
moduleList.push({
name: 'desktopCapturer',
loader: () => require('@electron/internal/renderer/api/desktop-capturer')
});
}
if (features.isRemoteModuleEnabled() && process.isRemoteModuleEnabled) {
if (BUILDFLAG(ENABLE_REMOTE_MODULE) && process.isRemoteModuleEnabled) {
moduleList.push({
name: 'remote',
loader: () => require('@electron/internal/renderer/api/remote')

View File

@@ -1,25 +1,19 @@
'use strict';
/* eslint no-eval: "off" */
/* global binding, Buffer */
const events = require('events');
import { electronBindingSetup } from '@electron/internal/common/electron-binding-setup';
import * as events from 'events';
const { EventEmitter } = events;
process.electronBinding = require('@electron/internal/common/electron-binding-setup').electronBindingSetup(binding.get, 'renderer');
process.electronBinding = electronBindingSetup(binding.get, 'renderer');
const v8Util = process.electronBinding('v8_util');
// Expose Buffer shim as a hidden value. This is used by C++ code to
// deserialize Buffer instances sent from browser process.
v8Util.setHiddenValue(global, 'Buffer', Buffer);
// The `lib/renderer/api/ipc-renderer.ts` module looks for the ipc object in the
// "ipc" hidden value
v8Util.setHiddenValue(global, 'ipc', new EventEmitter());
// The `lib/renderer/ipc-renderer-internal.ts` module looks for the ipc object in the
// "ipc-internal" hidden value
v8Util.setHiddenValue(global, 'ipc-internal', new EventEmitter());
// The process object created by webpack is not an event emitter, fix it so
// the API is more compatible with non-sandboxed renderers.
for (const prop of Object.keys(EventEmitter.prototype)) {
for (const prop of Object.keys(EventEmitter.prototype) as (keyof typeof process)[]) {
if (Object.prototype.hasOwnProperty.call(process, prop)) {
delete process[prop];
}
@@ -43,17 +37,22 @@ process.isRemoteModuleEnabled = isRemoteModuleEnabled;
// The electron module depends on process.electronBinding
const electron = require('electron');
const loadedModules = new Map([
const loadedModules = new Map<string, any>([
['electron', electron],
['events', events],
['timers', require('timers')],
['url', require('url')]
['electron/common', electron],
['electron/renderer', electron],
['events', events]
]);
const loadableModules = new Map<string, Function>([
['timers', () => require('timers')],
['url', () => require('url')]
]);
// ElectronApiServiceImpl will look for the "ipcNative" hidden object when
// invoking the 'onMessage' callback.
v8Util.setHiddenValue(global, 'ipcNative', {
onMessage (internal, channel, ports, args, senderId) {
onMessage (internal: boolean, channel: string, ports: MessagePort[], args: any[], senderId: number) {
const sender = internal ? ipcRendererInternal : electron.ipcRenderer;
sender.emit(channel, { sender, senderId, ports }, ...args);
}
@@ -62,16 +61,16 @@ v8Util.setHiddenValue(global, 'ipcNative', {
// ElectronSandboxedRendererClient will look for the "lifecycle" hidden object when
v8Util.setHiddenValue(global, 'lifecycle', {
onLoaded () {
process.emit('loaded');
(process as events.EventEmitter).emit('loaded');
},
onExit () {
process.emit('exit');
(process as events.EventEmitter).emit('exit');
},
onDocumentStart () {
process.emit('document-start');
(process as events.EventEmitter).emit('document-start');
},
onDocumentEnd () {
process.emit('document-end');
(process as events.EventEmitter).emit('document-end');
}
});
@@ -80,7 +79,7 @@ webFrameInit();
// Pass different process object to the preload script(which should not have
// access to things like `process.electronBinding`).
const preloadProcess = new EventEmitter();
const preloadProcess: NodeJS.Process = new EventEmitter() as any;
Object.assign(preloadProcess, binding.process);
Object.assign(preloadProcess, processProps);
@@ -97,30 +96,38 @@ Object.defineProperty(preloadProcess, 'noDeprecation', {
}
});
process.on('loaded', () => preloadProcess.emit('loaded'));
process.on('exit', () => preloadProcess.emit('exit'));
process.on('document-start', () => preloadProcess.emit('document-start'));
process.on('document-end', () => preloadProcess.emit('document-end'));
process.on('loaded', () => (preloadProcess as events.EventEmitter).emit('loaded'));
process.on('exit', () => (preloadProcess as events.EventEmitter).emit('exit'));
(process as events.EventEmitter).on('document-start', () => (preloadProcess as events.EventEmitter).emit('document-start'));
(process as events.EventEmitter).on('document-end', () => (preloadProcess as events.EventEmitter).emit('document-end'));
// This is the `require` function that will be visible to the preload script
function preloadRequire (module) {
function preloadRequire (module: string) {
if (loadedModules.has(module)) {
return loadedModules.get(module);
}
if (loadableModules.has(module)) {
const loadedModule = loadableModules.get(module)!();
loadedModules.set(module, loadedModule);
return loadedModule;
}
throw new Error(`module not found: ${module}`);
}
// Process command line arguments.
const { hasSwitch } = process.electronBinding('command_line');
// Similar to nodes --expose-internals flag, this exposes electronBinding so
// that tests can call it to get access to some test only bindings
if (hasSwitch('unsafely-expose-electron-internals-for-testing')) {
preloadProcess.electronBinding = process.electronBinding;
}
const contextIsolation = hasSwitch('context-isolation');
const isHiddenPage = hasSwitch('hidden-page');
const rendererProcessReuseEnabled = hasSwitch('disable-electron-site-instance-overrides');
const usesNativeWindowOpen = true;
// The arguments to be passed to isolated world.
const isolatedWorldArgs = { ipcRendererInternal, guestInstanceId, isHiddenPage, openerId, usesNativeWindowOpen, rendererProcessReuseEnabled };
switch (window.location.protocol) {
case 'devtools:': {
// Override some inspector APIs.
@@ -146,11 +153,6 @@ if (process.isMainFrame) {
webViewInit(contextIsolation, isWebViewTagEnabled, guestInstanceId);
}
// Pass the arguments to isolatedWorld.
if (contextIsolation) {
v8Util.setHiddenValue(global, 'isolated-world-args', isolatedWorldArgs);
}
// Wrap the script into a function executed in global scope. It won't have
// access to the current scope, so we'll expose a few objects as arguments:
//
@@ -158,7 +160,7 @@ if (contextIsolation) {
// - `process`: The `preloadProcess` object
// - `Buffer`: Shim of `Buffer` implementation
// - `global`: The window object, which is aliased to `global` by webpack.
function runPreloadScript (preloadSrc) {
function runPreloadScript (preloadSrc: string) {
const preloadWrapperSrc = `(function(require, process, Buffer, global, setImmediate, clearImmediate, exports) {
${preloadSrc}
})`;

View File

@@ -1,6 +1,6 @@
{
"name": "electron",
"version": "10.0.0-nightly.20200505",
"version": "11.0.0-nightly.20200604",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {
@@ -46,6 +46,7 @@
"lint-staged": "^8.1.0",
"minimist": "^1.2.0",
"nugget": "^2.0.1",
"null-loader": "^4.0.0",
"pre-flight": "^1.1.0",
"remark-cli": "^4.0.0",
"remark-preset-lint-markdown-style-guide": "^2.1.1",

View File

@@ -66,7 +66,6 @@ disable_compositor_recycling.patch
allow_new_privileges_in_unsandboxed_child_processes.patch
expose_setuseragent_on_networkcontext.patch
feat_add_set_theme_source_to_allow_apps_to.patch
revert_cleanup_remove_menu_subtitles_sublabels.patch
add_webmessageportconverter_entangleandinjectmessageportchannel.patch
revert_remove_contentrendererclient_shouldfork.patch
ignore_rc_check.patch
@@ -89,3 +88,14 @@ feat_add_onclose_to_messageport.patch
fix_account_for_print_preview_disabled_when_printing_to_pdf.patch
web_contents.patch
ui_gtk_public_header.patch
refactor_expose_cursor_changes_to_the_webcontentsobserver.patch
crash_allow_setting_more_options.patch
breakpad_treat_node_processes_as_browser_processes.patch
upload_list_add_loadsync_method.patch
breakpad_allow_getting_string_values_for_crash_keys.patch
crash_allow_disabling_compression_on_linux.patch
allow_setting_secondary_label_via_simplemenumodel.patch
disable_unnecessary_ischromefirstrun_check.patch
disable_dcheck_that_fails_with_software_compositing.patch
fix_swap_global_proxies_before_initializing_the_windows_proxies.patch
fix_default_to_ntlm_v2_in_network_service.patch

View File

@@ -10,18 +10,18 @@ This patch makes three changes to Accelerator::GetShortcutText to improve shortc
3. Ctrl-Shift-= should show as Ctrl-+
diff --git a/ui/base/accelerators/accelerator.cc b/ui/base/accelerators/accelerator.cc
index 291bdeec97bec510f7c86a8e8bccab22b7d5d8ac..926a705c23bd5adbfc0fe178c44617086b946a80 100644
index 7f26ef86fe967663a50bb556b49a37e1d10d5462..c83431034b9ddf0084f2ee2fc2538e4fb5aa0f0c 100644
--- a/ui/base/accelerators/accelerator.cc
+++ b/ui/base/accelerators/accelerator.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
@@ -12,6 +12,7 @@
#include "base/notreached.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "ui/base/l10n/l10n_util.h"
@@ -22,9 +23,7 @@
@@ -23,9 +24,7 @@
#include <windows.h>
#endif
@@ -31,7 +31,7 @@ index 291bdeec97bec510f7c86a8e8bccab22b7d5d8ac..926a705c23bd5adbfc0fe178c4461708
#if defined(OS_CHROMEOS)
#include "ui/base/ui_base_features.h"
@@ -220,7 +219,15 @@ base::string16 Accelerator::GetShortcutText() const {
@@ -204,7 +203,15 @@ base::string16 Accelerator::GetShortcutText() const {
shortcut = KeyCodeToName();
#endif
@@ -47,7 +47,7 @@ index 291bdeec97bec510f7c86a8e8bccab22b7d5d8ac..926a705c23bd5adbfc0fe178c4461708
#if defined(OS_WIN)
// Our fallback is to try translate the key code to a regular character
// unless it is one of digits (VK_0 to VK_9). Some keyboard
@@ -229,21 +236,14 @@ base::string16 Accelerator::GetShortcutText() const {
@@ -213,21 +220,14 @@ base::string16 Accelerator::GetShortcutText() const {
// accent' for '0'). For display in the menu (e.g. Ctrl-0 for the
// default zoom level), we leave VK_[0-9] alone without translation.
wchar_t key;
@@ -75,7 +75,7 @@ index 291bdeec97bec510f7c86a8e8bccab22b7d5d8ac..926a705c23bd5adbfc0fe178c4461708
}
#if defined(OS_MACOSX)
@@ -426,7 +426,7 @@ base::string16 Accelerator::ApplyLongFormModifiers(
@@ -410,7 +410,7 @@ base::string16 Accelerator::ApplyLongFormModifiers(
// more information.
if (IsCtrlDown())
shortcut = ApplyModifierToAcceleratorString(shortcut, IDS_APP_CTRL_KEY);

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