Compare commits

..

94 Commits

Author SHA1 Message Date
Electron Bot
30db185060 Bump v10.0.0-beta.11 2020-07-13 08:32:43 -07:00
Electron Bot
c804212426 chore: bump chromium in DEPS to 85.0.4183.20 (#24487) 2020-07-09 19:57:43 -07:00
Electron Bot
7a5b18b0d6 Bump v10.0.0-beta.10 2020-07-09 08:33:13 -07:00
Electron Bot
d608a30015 chore: bump chromium to 85.0.4183.19 (10-x-y) (#24299)
* chore: bump chromium in DEPS to 85.0.4182.1

* chore: bump chromium in DEPS to 85.0.4183.2

* chore: bump chromium in DEPS to 85.0.4183.4

* chore: bump chromium in DEPS to 85.0.4183.5

* update patches

* chore: bump chromium in DEPS to 85.0.4183.6

* chore: bump chromium in DEPS to 85.0.4183.7

* update patches

* chore: bump chromium in DEPS to 85.0.4183.8

* remove chromeos-only TtsControllerDelegate

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2255314
(cherry picked from commit f975f84a3c)

* rename GetHighContrastColorScheme -> GetPlatformHighContrastColorScheme

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2250224
(cherry picked from commit 014b487258)

* add max_xcode_version build var

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2264867
(cherry picked from commit 2c3b94f497)

* add empty floc blocklist to BrowserProcessImpl

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2240873
(cherry picked from commit 3cdaae146d)

* Move zygote from //services/service_manager back to //content

https://chromium-review.googlesource.com/c/chromium/src/+/2252466
(cherry picked from commit e0d6dbcf1e)

* Reland "[base] Stop including check.h, notreached.h, etc. in logging.h"

https://chromium-review.googlesource.com/c/chromium/src/+/2264297
(cherry picked from commit 1407040133)

* Update mas private api patch

* Reland "Reland "New toolchain for Windows 10 19041 SDK""

https://chromium-review.googlesource.com/c/chromium/src/+/2255527
(cherry picked from commit 8101d956f5)

* [XProto] Remove usage of Shape extension

https://chromium-review.googlesource.com/c/chromium/src/+/2262113
(cherry picked from commit 72b6f11958)

* chore: bump chromium in DEPS to 85.0.4183.9

* chore: bump chromium in DEPS to 85.0.4183.10

* chore: bump chromium in DEPS to 85.0.4183.11

* chore: bump chromium in DEPS to 85.0.4183.12

* chore: bump chromium in DEPS to 85.0.4183.13

* update patches

* fixup! add empty floc blocklist to BrowserProcessImpl

(cherry picked from commit 07b0b65c1d)

* fixup! Reland "[base] Stop including check.h, notreached.h, etc. in logging.h"

(cherry picked from commit f91c1ab162)

* Check for GDI exhaustion if window creation fails

https://chromium-review.googlesource.com/c/chromium/src/+/2244124
(cherry picked from commit 3d45d7b78c)

* chore: bump chromium in DEPS to 85.0.4183.14

* Fixup lint issue

* update patches

* fix: include missing header file

* chore: bump chromium in DEPS to 85.0.4183.19

* update patches

* refactor: match upstream print preview handling (#24452)

(cherry picked from commit 004e29ad33)

* use PrintHostMsg_DidPreviewPage_Params

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

Co-authored-by: Andy Locascio <andy@slack-corp.com>
Co-authored-by: Electron Bot <anonymous@electronjs.org>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-07-09 10:04:19 -04:00
trop[bot]
74efe8d834 fix: clipboard.readBuffer returning empty value (#24467)
Co-authored-by: Deepak Mohan <hop2deep@gmail.com>
2020-07-08 17:22:58 -07:00
trop[bot]
3283211a15 fix: uv_walk crash on web worker close (#24462)
* fix: uv_walk crash on web worker close

* Use DCHECK_EQ

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-07-08 13:07:53 -07:00
trop[bot]
d4a6affa4b fix: use try/catch for base class converter error (#24450)
* fix: use try/catch for base class converter error

* Place try/catch in a block

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-07-07 20:00:46 -07:00
trop[bot]
73e13ab6d6 chore: add missing _Deprecated_ to 'renderer-process-crashed' on app (#24432)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-07-06 16:08:57 -04:00
trop[bot]
c32c69604a feat: expose sessionId in debugger module (#24397)
Co-authored-by: deepak1556 <hop2deep@gmail.com>
2020-07-06 12:38:01 -07:00
Electron Bot
2761be6467 Bump v10.0.0-beta.9 2020-07-06 08:32:36 -07:00
Milan Burda
30cb2b134b test: make sure tests fail properly instead of timing out (#24372)
* test: use delay() helper (#24321)

* test: make sure tests fail properly instead of timing out (#24316)

* test: remove defer()

Co-authored-by: Milan Burda <miburda@microsoft.com>
2020-07-03 18:55:56 -07:00
trop[bot]
48cd3eeced chore: use node_bindings loop for clarity (#24416)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-07-03 18:47:37 -07:00
trop[bot]
831b6fa227 fix: intermittent 100% CPU usage on macOS (#24413)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-07-03 11:25:18 -07:00
trop[bot]
91ce51cfb3 fix: remove same-tag notifications before showing new ones (#24404)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-07-03 09:20:53 -07:00
Electron Bot
bf1870facc Bump v10.0.0-beta.8 2020-07-02 08:35:19 -07:00
trop[bot]
39bc7c82a6 feat: implement systemPreferences.getMediaAccessStatus() on Windows (#24311)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-07-01 16:51:10 -07:00
trop[bot]
991d982622 ci: update timeout on breakpad generation to 30 minutes (#24387)
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-07-01 11:59:16 -04:00
trop[bot]
195662ead0 fix: macOS modal focus (#24352)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-06-29 15:49:33 -07:00
trop[bot]
d580cc1578 feat: support suspend/resume on Windows (#24281)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-06-29 09:07:16 -07:00
trop[bot]
d8de43f534 feat: support suspend/resume on macOS (#24293)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-06-29 09:06:00 -07:00
Electron Bot
c48a6b48c9 Bump v10.0.0-beta.7 2020-06-29 08:31:24 -07:00
Electron Bot
d701c292a0 Bump v10.0.0-beta.6 2020-06-25 08:31:59 -07:00
Electron Bot
19e7af9841 chore: bump chromium to 85.0.4181.1 (10-x-y) (#23987)
* chore: bump chromium in DEPS to 85.0.4165.1

* chore: bump chromium in DEPS to 85.0.4166.1

* chore: bump chromium in DEPS to 85.0.4166.2

* chore: bump chromium in DEPS to 85.0.4166.3

* update patches

* fixup! Revert "[printing] Mojofy PrintHostMsg_CheckForCancel"

(cherry picked from commit 2cc1caf5d7d716ceefb23d5228a79544a2e91206)

* update patches

* Revert "[printing] Mojofy PrintHostMsg_CheckForCancel"

(cherry picked from commit c2b389957836ad77eb8e977872e6a8590666f3da)

* Remove WebImeTextSpan

https://chromium-review.googlesource.com/c/chromium/src/+/2225240
(cherry picked from commit d839261d71b156c972d3878f16f971e6b6d98f45)

* Remove PDFAnnotations flag altogether.

https://chromium-review.googlesource.com/c/chromium/src/+/2229317
(cherry picked from commit 50384ed12602d4a9da3209eacfca4faae78f9986)

* Rework find-from-selection so it's synchronous -- fixes flaky tests

https://chromium-review.googlesource.com/c/chromium/src/+/2181570
(cherry picked from commit 3e9241560390fb18969393beda425afc63f5a151)

* Use ExtensionSystem::is_ready() instead of ExtensionService::is_ready()

https://chromium-review.googlesource.com/c/chromium/src/+/2207499
(cherry picked from commit 2424589454a9a2ef9cc89c232b4ee87b0bf400cc)

* update sysroots

(cherry picked from commit b5ea653e602152dde00303d1cfb915d4df320983)

* chore: bump chromium in DEPS to 85.0.4167.1

* Take RFH as a parameter for DidUpdateFavicon/ManifestURL

https://chromium-review.googlesource.com/c/chromium/src/+/2224745
(cherry picked from commit ad40668221732e28bcc8b9b270ab4686c42e956a)

* update patches

* update patches

* Rename net::cookie_util::StripStatuses to StripAccessResults

https://chromium-review.googlesource.com/c/chromium/src/+/2212697
(cherry picked from commit bf3de1fe1cbb17feb46b40c81f0eb13b1e7b6412)

* use net::CookieAccessResultList instead of net::CookieAccessResultList

(cherry picked from commit 400da79504da2310b7c1177b4b3f9f83a3f2b305)

* chore: bump chromium in DEPS to 85.0.4168.1

* fix mas_no_private_api patch

https://chromium-review.googlesource.com/c/chromium/src/+/2230281
(cherry picked from commit 9b127147e0ba7ef1d4454099effe49327b1a5ab6)

* Update patches

* fix: add new navigation state REUSE_SITE_INSTANCE

To fix the new set of state checks added in
https://chromium-review.googlesource.com/c/chromium/src/+/2215141

(cherry picked from commit 3a91b684efdc7742e7c5efa65263f80e8a24ec4a)

* chore: bump chromium in DEPS to 85.0.4169.1

* update patches

* chore: bump chromium in DEPS to 85.0.4170.1

* chore: bump chromium in DEPS to 85.0.4171.1

* chore: bump chromium in DEPS to 85.0.4172.1

* chore: bump chromium in DEPS to 85.0.4173.1

* chore: bump chromium in DEPS to 85.0.4174.1

* chore: bump chromium in DEPS to 85.0.4175.3

* chore: bump chromium in DEPS to 85.0.4176.1

* chore: bump chromium in DEPS to 85.0.4177.2

* chore: bump chromium in DEPS to 85.0.4178.1

* chore: bump chromium in DEPS to 85.0.4178.3

* refactor: MessageLoop, you are terminated \o/

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2246173
(cherry picked from commit 0368131d60)

* chore: bump chromium in DEPS to 85.0.4178.4

* update patches

* update lib_src_switch_buffer_kmaxlength_to_size_t.patch

(cherry picked from commit c5efbdd166)

* [v8] Allow for 4GB TypedArrays

https: //chromium-review.googlesource.com/c/v8/v8/+/2249668
(cherry picked from commit 2c1d6bfd9d)
Co-Authored-By: Robo <hop2deep@gmail.com>

* Cleanup usages of old mojo types and remove unused code

https://chromium-review.googlesource.com/c/chromium/src/+/2235699
(cherry picked from commit e89cb21e8e)

* refactor: plumb DownloadSchedule to DownloadItem

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2242202
(cherry picked from commit 4d549ae2b0)

* chore: fix variable typo in IPC

(cherry picked from commit 7251b1e6c5)

* chore: s/BindPipeAndPassReceiver/BindNewPipeAndPassReceiver

(cherry picked from commit e89bd6c639)

* chore: XEvent becomes x11::Event

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2240355
(cherry picked from commit 4d832da740)

* fixup! refactor: MessageLoop, you are terminated \o/

(cherry picked from commit 902d72d740)

* fixup! chore: XEvent becomes x11::Event

(cherry picked from commit 27043549f3)

* chore: fix windows build

(cherry picked from commit 4977098eb3)

* chore: disable SameSite-by-default changes

https://chromium-review.googlesource.com/c/chromium/src/+/2231445
(cherry picked from commit d8318aafff)

* update printing.patch

(cherry picked from commit e2037f527f)

* Convert WidgetHostMsg_SelectionBoundsChanged/TextInputStateChanged

https://chromium-review.googlesource.com/c/chromium/src/+/2243531
(cherry picked from commit 60ff2e067d)

* [XProto] Replace usages of XID and ::Window with x11::Window

https://chromium-review.googlesource.com/c/chromium/src/+/2249389
(cherry picked from commit 97f5b59e06)

* Update VideoFrameMetadata to use base::Optionals

https://chromium-review.googlesource.com/c/chromium/src/+/2231706
https://chromium-review.googlesource.com/c/chromium/src/+/2238361
(cherry picked from commit 4787e1f541)

* --disable-dev-shm-usage for gpu process crash

(cherry picked from commit 207d8a380a)

* update patches

* fixup: Cleanup usages of old mojo types and remove unused code

* update patches

* chore: bump chromium in DEPS to 85.0.4180.1

* build: update v8 headers

(cherry picked from commit 4808975f75)

* Update patches

* fixup: build: update v8 headers

* Fixup ssl_security_state_tab_helper.patch

* Add missing headers

* Adds icon loading service with sandbox for Windows.

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

* disable app.getGPUInfo spec on linux

(cherry picked from commit b7ea16c4b7)

* Add missing headers for Linux and Windows

* Fixup Adds icon loading service with sandbox for Windows

* chore: bump chromium in DEPS to 85.0.4181.1

* update patches

* Fixup: (for real) Adds icon loading service with sandbox for Windows

* No more Vulkan info collection for UMA on Windows

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

* extensions: Rename SharedUserScriptMaster to SharedUserScriptManager

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

* Add missing headers

* fixup: extensions: Rename SharedUserScriptMaster to SharedUserScriptManager

* fixup: No more Vulkan info collection for UMA on Windows

* Add missing header

* Add resource for IDS_UTILITY_PROCESS_UTILITY_WIN_NAME

* fix build on windows

* fix gn check

Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
Co-authored-by: Electron Bot <anonymous@electronjs.org>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-06-25 00:48:48 -07:00
trop[bot]
86e4a96f45 chore: minify internal JS code (#24272)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-06-24 19:37:23 -07:00
trop[bot]
e059ae7bd6 fix: frameless vibrant modals shouldn't bezel (#24284)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-06-24 10:15:26 -07:00
Jeremy Rose
fb292c26d5 fix: backport nodejs/node#33682 (#24266) 2020-06-24 00:57:50 -07:00
trop[bot]
0e0dd6460f fix: emit click events with tray context menu (#24235)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-06-22 19:02:54 -07:00
Electron Bot
b464589143 Bump v10.0.0-beta.5 2020-06-22 08:32:33 -07:00
trop[bot]
ee372c152a fix: isTrustedSender() in test-app (#24230)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-06-22 08:24:23 -07:00
trop[bot]
53bdc4a71b build: remove dead symlink from MAS build (#24166) 2020-06-18 17:40:34 -07:00
trop[bot]
ab0960ecd9 fix: do not use CONTEXT_MENU flag for tray menu (reland) (#24192)
* fix: menu window should not appear in taskbar

* fix: do not use CONTEXT_MENU flag for tray menu

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-06-18 14:43:20 -07:00
Electron Bot
29c9c80c89 Bump v10.0.0-beta.4 2020-06-18 08:32:38 -07:00
trop[bot]
72f2dad3a1 Make pasteandmatchstyle accelerator OS specific (#24182)
Co-authored-by: Elena Topaka <el1topa@gmail.com>
2020-06-17 21:47:47 -07:00
trop[bot]
64cdfda810 fix: let Node.js perform microtask checkpoint in the main process (#24174)
* fix: let Node.js perform microtask checkpoint in the main process

* fix: don't specify v8::MicrotasksScope for explicit policy

* fix: remove checkpoint from some call-sites

We already perform checkpoint at the end of a task,
either through MicrotaskRunner or through NodeBindings.
There isn't a need to add them again when calling into JS
except when dealing with promises.

* fix: remove checkpoint from some call-sites

We already perform checkpoint at the end of a task,
either through MicrotaskRunner or through NodeBindings.
There isn't a need to add them again when calling into JS
except when dealing with promises.

* fix incorrect specs

* default constructor arguments are considered for explicit mark

* add regression spec

Co-authored-by: deepak1556 <hop2deep@gmail.com>
2020-06-17 12:48:31 -07:00
trop[bot]
9f8f82af00 docs: fix MenuItem click handler type (#24175)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-06-17 11:30:11 -07:00
trop[bot]
306d76b317 fix: emit 'shutdown' outside -[NSApplication terminate:] (#24139)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-06-16 10:03:09 -07:00
trop[bot]
097c501cf5 fix: handle non-client area pointer events from pen on Win10 (#24102) 2020-06-15 21:01:47 -07:00
Electron Bot
d4bc4e1d4c Bump v10.0.0-beta.3 2020-06-15 08:31:31 -07:00
trop[bot]
0c861dc83e fix: correctly handle nexttick scheduling in stream reads (#24081)
Co-authored-by: Paul Frazee <pfrazee@gmail.com>
2020-06-15 19:00:13 +09:00
trop[bot]
57b766aa82 fix: showing certificate dialog with no window (#24118)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-06-13 08:22:36 -07:00
trop[bot]
4b8295a24d fix: fs.readdir should support withFileTypes (#24106)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-06-12 13:42:17 -07:00
Samuel Attard
710199c308 Revert "fix: do not use CONTEXT_MENU flag for tray menu (#23879)" (#24077)
This reverts commit d4001c1787.
2020-06-11 14:27:25 -04:00
Shelley Vohr
c2d9cde38f chore: roll latest Node.js security release (#23945) 2020-06-11 11:18:10 -07:00
trop[bot]
fbaca68bd0 fix: Add .paks for media-internals and webrtc-internals pages (#24057)
* fix: adds paks for media-internals and webrtc-internals pages

* adds tests

Co-authored-by: gellert <gellert.hegyi@around.co>
2020-06-11 09:26:01 -07:00
trop[bot]
ee9f95df30 fix: assign session to remote webContents (#24064)
* fix: assign session to remote webContents

* fix: test name

Co-authored-by: sentialx <sentialx@gmail.com>
2020-06-11 08:49:59 -07:00
trop[bot]
9df936d941 fix: use system installed objcopy to copy debug symbols (#24031)
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-06-11 10:56:59 +09:00
trop[bot]
baa2940488 fix: Allow windows behind macOS elements if frame = false (#24032)
Co-authored-by: Felix Rieseberg <felix@felixrieseberg.com>
2020-06-11 10:56:25 +09:00
trop[bot]
25879ba929 chore: backport advapi32 libuv fix (#24038)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-06-11 10:55:22 +09:00
Electron Bot
34b04e5fbb Revert "Bump v10.0.0-beta.3"
This reverts commit 710ac2a5a8.
2020-06-09 12:02:57 -07:00
Electron Bot
710ac2a5a8 Bump v10.0.0-beta.3 2020-06-09 08:50:04 -07:00
trop[bot]
1f0d2594bd fix: throw instead of crash when using ipcRenderer after context released (#23977)
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-06-08 11:36:32 -07:00
trop[bot]
656d9e7490 build: fix filenames autogen with new BUILDFLAG syntax (#23958)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-06-08 11:09:34 -07:00
trop[bot]
5bf938f899 fix: add missing isComposing KeyboardEvent property (#23995)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-06-08 10:51:12 -05:00
trop[bot]
7759048136 fix: volume key globalShortcut deregistration (#24012)
Co-authored-by: Aleksei Kuzmin <alkuzmin@microsoft.com>
2020-06-08 10:50:17 -04:00
trop[bot]
321c1c1075 fix: use acceptLanguages argument in session.setUserAgent() (#23961)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-06-05 09:46:03 -07:00
trop[bot]
d69d1bbf20 fix: missing handlescoped in touch bar (#23970)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-06-04 19:34:17 -07:00
trop[bot]
f3dd997dbd feat: add V8CacheOptions webpreference (#23867)
* feat: add V8CacheOptions webpreference

* address review comments

Co-authored-by: deepak1556 <hop2deep@gmail.com>
2020-06-04 17:15:44 -04:00
trop[bot]
faf7951439 fix: destroy GetSize callback at last (#23954)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-06-03 15:54:24 -04:00
trop[bot]
3087492994 fix: compensate for lazy-loaded circular deps (#23951)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-06-03 15:18:55 -04:00
John Kleinschmidt
f7e4377ee8 chore: update chromium to 85.0.4161.2 (#23915)
* chore: update 10-x-y to 85.0.4161.2

* Update patches

* chore: SetHostCleanupFinalizationGroupCallback has been removed from V8

(cherry picked from commit 7aa3058829)

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

https://chromium-review.googlesource.com/c/chromium/src/+/2203268
(cherry picked from commit fdccae9246)

* refactor: GetSublabelAt => GetSecondaryLabelAt

(cherry picked from commit cc8be2f634)

* refactor: use WebInputEvent::Namespace types directly

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2160523
(cherry picked from commit f35200077e)

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

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2174654
(cherry picked from commit c2a4d1b515)

* remove WebContentsView::SizeContents

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2188931
(cherry picked from commit f4ccf3556c)

* adapt to //content creating NetworkContexts

https://chromium-review.googlesource.com/c/chromium/src/+/2195196
(cherry picked from commit 6834366747)

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

https://chromium-review.googlesource.com/c/chromium/src/+/2212481
(cherry picked from commit 68c8ea6ea9)

* fixup patch

* refactor: AddNewContents now takes a target_url

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2167732
(cherry picked from commit 69fe1f6f47)

* refactor: FollowRedirect takes in cors exempt headers now

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2129787
(cherry picked from commit 58f3770c19)

* refactor: printing::DuplexMode moved to mojo

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2162388
(cherry picked from commit a14cdc465a)

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

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/1952124
(cherry picked from commit dce81ad06f)

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

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2172874
(cherry picked from commit 7f3c13de3f)

* refactor: shuttle cursor changed event to WebContentsObserver

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2172779
(cherry picked from commit 2f3a23afb7)
Co-Authored-By: loc <loc@users.noreply.github.com>

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

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2173666
(cherry picked from commit d9152c3668)

* remove ClientSideDetectionService from browser_process

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2175320
(cherry picked from commit 2461522752)

* Remove cors_exempt_headers.h

https://chromium-review.googlesource.com/c/chromium/src/+/2203759
(cherry picked from commit b73faa6411)

* [content] Remove unused methods from WebContents

https://chromium-review.googlesource.com/c/chromium/src/+/2199113
(cherry picked from commit 8b9ea9cd2b)

* Unnest CanonicalCookie::CookieInclusionStatus

https://chromium-review.googlesource.com/c/chromium/src/+/2203171
(cherry picked from commit 7d4349b37c)

* WebContentsObserver now implements OnRendererResponsive

https://chromium-review.googlesource.com/c/chromium/src/+/2211066
(cherry picked from commit 53f32b7e45)

* chore: remove NOTIFICATION_EXTENSIONS_READY_DEPRECATED

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2199874
(cherry picked from commit 7914445469)

* Supply speech recognition sandbox from service_sandbox_type.h

https://chromium-review.googlesource.com/c/chromium/src/+/2206918
(cherry picked from commit f15a0fdfab)

* [XProto] Replace XAtom with x11::Atom

https://chromium-review.googlesource.com/c/chromium/src/+/2202789
(cherry picked from commit 143110105a)

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

https://bugs.chromium.org/p/chromium/issues/detail?id=1085667
(cherry picked from commit 205105fc16)

* fix build on windows

(cherry picked from commit 0a255c4fa7)

* [printing] Mojofy PrintHostMsg_CheckForCancel

https://chromium-review.googlesource.com/c/chromium/src/+/2212181
(cherry picked from commit 4f1064afa9)

* chore: update sysroots

(cherry picked from commit 2a1b78a4bf)

* chore: DesktopWindowTreeHostLinux becomes DesktopWindowTreeHostPlatform

Refs:
(cherry picked from commit 3fd0875d3d)

* refactor: LogErrorEventDescription moved from ui to x11

Refs: https://chromium-review.googlesource.com/c/chromium/src/+/2164245
(cherry picked from commit 9291fc4afc)

* fix: inherit base network context params

(cherry picked from commit 698c66f7f9)

* fix: use message handle api specific to embedders

(cherry picked from commit 23d01dc8e0)

* chore: update v8 headers

(cherry picked from commit 81bc1e0bee)

* add checkout_pgo_profiles to DEPS

(cherry picked from commit 9b73e6935c)

* 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>
(cherry picked from commit de074ce23a)

* [printing] Mojofy PrintHostMsg_PrintPreviewCancelled

https://chromium-review.googlesource.com/c/chromium/src/+/2198331
(cherry picked from commit 7bd8a6a576)

* [printing] Mojofy PrintHostMsg_PrintPreviewInvalidPrinterSettings

https://chromium-review.googlesource.com/c/chromium/src/+/2200556
(cherry picked from commit dd68ba1ecf)

* Network service: Remove primary_network_context bool.

https://chromium-review.googlesource.com/c/chromium/src/+/2204678
(cherry picked from commit 6a0e8e5bf9)

* [printing] Move PrintHostMsg_DidPrintContent_Params to print.mojom

https://chromium-review.googlesource.com/c/chromium/src/+/2212110
(cherry picked from commit a6a3291d9a)

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

https://chromium-review.googlesource.com/c/chromium/src/+/2218476
(cherry picked from commit b16c48830a)

* Update patches

* Remove no longer needed patch

* update patches

* update patches

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
Co-authored-by: Andy Locascio <andy@slack-corp.com>
Co-authored-by: loc <loc@users.noreply.github.com>
Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-06-03 14:38:01 -04:00
trop[bot]
ef288a6ae2 fix: restore original GTK/appindicator implementation of tray icons (#23925)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-06-03 10:14:53 -07:00
trop[bot]
7797835f93 test: load page with some content when testing extension (#23939)
* test: load page with some content when testing extension

* test: use dom-ready to wait for page loaded with extension

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-06-03 09:51:06 -07:00
trop[bot]
9572209e91 fix: correctly support the --inspect-brk-node flag (#23918)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-06-03 17:01:17 +09:00
trop[bot]
3602216e6c fix: default to NTLM v2 in the network service for POSIX platforms (#23916)
* fix: default to NTLM v2 in the network service

* chore: update patch details

* update patches

Co-authored-by: deepak1556 <hop2deep@gmail.com>
Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-06-02 20:58:38 -07:00
trop[bot]
c29382b6d0 fix: Make the --disable-color-correct-rendering switch work again (#23899)
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`

Co-authored-by: Biru Mohanathas <birunthan@mohanathas.com>
2020-06-02 15:40:24 -04:00
trop[bot]
a8fc41d8b3 docs: default of allowRendererProcessReuse is true (#23912)
Co-authored-by: Samuel Attard <sattard@slack-corp.com>
2020-06-02 12:02:53 -07:00
trop[bot]
9ea42da40e docs: move protocol-ns to protocol.md (#23911)
* docs: move protocol-ns to protocol.md

* chore: fix up tests and implement missing pieces required for tests

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-06-02 10:55:50 -07:00
trop[bot]
87cd20b9e9 fix: add patch to prevent crash during frame swap with ctx isolation enabled (#23896)
* fix: add patch to prevent crash during frame swap with ctx isolation enabled

* Update .patches

* chore: update patches

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: Samuel Attard <sattard@slack-corp.com>
2020-06-02 10:55:14 -07:00
trop[bot]
79acd3e0ef fix: expose electron/common and electron/renderer modules in sandboxed preloads (#23893)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-06-02 14:23:19 +09:00
trop[bot]
67be46986c test: wait for beforeunload handler to be installed (#23898)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-06-02 14:21:42 +09:00
trop[bot]
d4001c1787 fix: do not use CONTEXT_MENU flag for tray menu (#23879)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-06-02 11:10:41 +09:00
trop[bot]
eeaad9c6ab build: make electron renderer init scripts profilable (#23891)
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.

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-06-01 17:38:33 -07:00
Alexey Kuzmin
cc0c7632ac build: fix for "enable_desktop_capturer = false" (#23864) (#23876)
(cherry picked from commit 4133c71105)
2020-06-01 17:23:33 -04:00
Electron Bot
12ea1c0c41 Bump v10.0.0-beta.2 2020-06-01 08:32:38 -07:00
Shelley Vohr
9d2aa93581 fix: ensure nativeImage serialization main->renderer (#23794)
* refactor: use typeutils for nativeImage serialization (#23693)

* fix: ensure nativeImage serialization main->renderer
2020-05-28 12:07:33 -07:00
trop[bot]
cee9e6f0d0 fix: weakly reference MenuModel from MenuController (#23806)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-05-28 09:47:43 -07:00
trop[bot]
eb93acc463 fix: handle asynchronous URL loading in bw proxy (#23804)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-05-28 09:41:54 -07:00
trop[bot]
241e74c098 test: refactor how spec files are collected (#23811)
Co-authored-by: Aleksei Kuzmin <alkuzmin@microsoft.com>
2020-05-28 09:40:59 -07:00
trop[bot]
c0183d15af fix: volume key globalShortcut registration (#23823)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-05-28 08:57:25 -07:00
trop[bot]
4fe7c9ac24 fix: only bezel frameless windows (#23809)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-05-28 08:52:58 -04:00
Cheng Zhao
50efa847a5 Revert "fix: trigger activate event when app is activated via app switcher (#23771)" (#23819)
This reverts commit 7709e600c6.
2020-05-28 08:47:55 -04:00
trop[bot]
c2354d44ea fix: pass correct buffer length (#23798)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-05-27 14:09:30 -07:00
trop[bot]
7709e600c6 fix: trigger activate event when app is activated via app switcher (#23771)
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-27 09:52:10 +09:00
trop[bot]
0962c1bd74 ci: deflake WOA tests (#23769)
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-05-26 13:22:55 -04:00
trop[bot]
471f80521d test: use WebContents event to test beforeunload (#23766)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-05-26 10:53:23 -04:00
trop[bot]
1fb11e1e76 fix: trigger about panel for about role on on win (#23717)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-05-22 00:55:25 -07:00
trop[bot]
f8508b3c18 fix: read GTK dark theme setting on Linux (#23711)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-05-21 21:07:42 -04:00
Electron Bot
95e3853b77 Bump v10.0.0-beta.1 2020-05-21 14:28:15 -07:00
Samuel Attard
9de5ede1fb Revert "feat: look harder for a commit's pull request. (#23593)"
This reverts commit 2342aaffbd.
2020-05-21 14:27:04 -07:00
Electron Bot
05efbbcdd5 Revert "Bump v10.0.0-beta.1"
This reverts commit 2789f32efb.
2020-05-21 14:23:22 -07:00
Electron Bot
2789f32efb Bump v10.0.0-beta.1 2020-05-21 14:23:00 -07:00
Samuel Attard
4c8b884998 fix: support 10-x-y in the release notes generator (#23709) 2020-05-21 14:13:17 -07:00
Electron Bot
03ddd2d7af Revert "Bump v10.0.0-beta.1"
This reverts commit c141b1a906.
2020-05-21 13:33:35 -07:00
Electron Bot
c141b1a906 Bump v10.0.0-beta.1 2020-05-21 13:33:02 -07:00
422 changed files with 6254 additions and 7602 deletions

View File

@@ -832,7 +832,7 @@ step-restore-out-cache: &step-restore-out-cache
paths:
- ./src/out/Default
keys:
- v9-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
- v8-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
name: Restoring out cache
step-set-git-cache-path: &step-set-git-cache-path
@@ -856,7 +856,7 @@ step-save-out-cache: &step-save-out-cache
save_cache:
paths:
- ./src/out/Default
key: v9-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
key: v8-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
name: Persisting out cache
step-run-electron-only-hooks: &step-run-electron-only-hooks

View File

@@ -15,7 +15,6 @@ 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

@@ -347,7 +347,6 @@ source_set("electron_lib") {
"//device/bluetooth",
"//device/bluetooth/public/cpp",
"//gin",
"//media/blink:blink",
"//media/capture/mojom:video_capture",
"//media/mojo/mojom",
"//net:extras",
@@ -497,17 +496,16 @@ source_set("electron_lib") {
} else {
libs += [
"Squirrel.framework",
"ReactiveObjC.framework",
"ReactiveCocoa.framework",
"Mantle.framework",
]
deps += [
"//third_party/squirrel.mac:reactiveobjc_framework+link",
"//third_party/squirrel.mac:squirrel_framework+link",
cflags_objcc = [
"-F",
rebase_path("external_binaries", root_build_dir),
]
# ReactiveObjC which is used by Squirrel requires using __weak.
cflags_objcc = [ "-fobjc-weak" ]
# ReactiveCocoa which is used by Squirrel requires using __weak.
cflags_objcc += [ "-fobjc-weak" ]
}
}
if (is_linux) {
@@ -603,6 +601,15 @@ source_set("electron_lib") {
]
}
if (enable_remote_module) {
sources += [
"shell/common/api/remote/remote_callback_freer.cc",
"shell/common/api/remote/remote_callback_freer.h",
"shell/common/api/remote/remote_object_freer.cc",
"shell/common/api/remote/remote_object_freer.h",
]
}
if (enable_desktop_capturer) {
if (is_component_build && !is_linux) {
# On windows the implementation relies on unexported
@@ -812,6 +819,8 @@ if (is_mac) {
}
ldflags = [
"-F",
rebase_path("external_binaries", root_build_dir),
"-Wl,-install_name,@rpath/$output_name.framework/$output_name",
"-rpath",
"@loader_path/Libraries",
@@ -862,49 +871,17 @@ if (is_mac) {
}
}
template("stripped_framework") {
action(target_name) {
assert(defined(invoker.framework))
script = "//electron/build/strip_framework.py"
forward_variables_from(invoker, [ "deps" ])
inputs = [ "$root_out_dir/" + invoker.framework ]
outputs = [ "$target_out_dir/stripped_frameworks/" + invoker.framework ]
args = rebase_path(inputs) + rebase_path(outputs)
}
}
stripped_framework("stripped_mantle_framework") {
framework = "Mantle.framework"
deps = [ "//third_party/squirrel.mac:mantle_framework" ]
}
stripped_framework("stripped_reactiveobjc_framework") {
framework = "ReactiveObjC.framework"
deps = [ "//third_party/squirrel.mac:reactiveobjc_framework" ]
}
stripped_framework("stripped_squirrel_framework") {
framework = "Squirrel.framework"
deps = [ "//third_party/squirrel.mac:squirrel_framework" ]
}
bundle_data("electron_app_framework_bundle_data") {
sources = [ "$root_out_dir/$electron_framework_name.framework" ]
if (!is_mas_build) {
sources += get_target_outputs(":stripped_mantle_framework") +
get_target_outputs(":stripped_reactiveobjc_framework") +
get_target_outputs(":stripped_squirrel_framework")
sources += [
"external_binaries/Mantle.framework",
"external_binaries/ReactiveCocoa.framework",
"external_binaries/Squirrel.framework",
]
}
outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ]
public_deps = [
":electron_framework+link",
":stripped_mantle_framework",
":stripped_reactiveobjc_framework",
":stripped_squirrel_framework",
]
public_deps = [ ":electron_framework+link" ]
foreach(helper_params, content_mac_helpers) {
sources +=
@@ -1102,9 +1079,7 @@ if (is_mac) {
data += [ "$root_out_dir/resources/default_app.asar" ]
}
if (use_v8_context_snapshot) {
public_deps = [ "//tools/v8_context_snapshot:v8_context_snapshot" ]
}
public_deps = [ "//tools/v8_context_snapshot:v8_context_snapshot" ]
if (is_win) {
sources += [
@@ -1212,6 +1187,18 @@ test("shell_browser_ui_unittests") {
"//ui/base",
"//ui/strings",
]
if (is_mac) {
# Resolve paths owing to different test executable locations
ldflags = [
"-F",
rebase_path("external_binaries", root_build_dir),
"-rpath",
"@loader_path",
"-rpath",
"@executable_path/" + rebase_path("external_binaries", root_build_dir),
]
}
}
template("dist_zip") {
@@ -1309,13 +1296,10 @@ dist_zip("electron_chromedriver_zip") {
mksnapshot_deps = [
":licenses",
"//tools/v8_context_snapshot:v8_context_snapshot_generator($v8_snapshot_toolchain)",
"//v8:mksnapshot($v8_snapshot_toolchain)",
]
if (use_v8_context_snapshot) {
mksnapshot_deps += [ "//tools/v8_context_snapshot:v8_context_snapshot_generator($v8_snapshot_toolchain)" ]
}
group("electron_mksnapshot") {
public_deps = mksnapshot_deps
}

33
DEPS
View File

@@ -8,18 +8,17 @@ gclient_gn_args = [
'checkout_pgo_profiles',
'checkout_oculus_sdk',
'checkout_openxr',
'checkout_google_benchmark'
'checkout_google_benchmark',
'mac_xcode_version',
]
vars = {
'chromium_version':
'9ae03ef8f7d4f6ac663f725bcfe70311987652f3',
'85.0.4183.20',
'node_version':
'v12.18.2',
'v12.16.3',
'nan_version':
'2c4ee8a32a299eada3cd6e468bbd0a473bfea96d',
'squirrel.mac_version':
'44468f858ce0d25c27bd5e674abfa104e0119738',
'boto_version': 'f7574aa6cc2c819430c1f05e9a1a1a666ef8169b',
'pyyaml_version': '3.12',
@@ -31,7 +30,6 @@ vars = {
'nodejs_git': 'https://github.com/nodejs',
'requests_git': 'https://github.com/kennethreitz',
'yaml_git': 'https://github.com/yaml',
'squirrel_git': 'https://github.com/Squirrel',
# KEEP IN SYNC WITH utils.js FILE
'yarn_version': '1.15.2',
@@ -54,6 +52,8 @@ vars = {
# Python "requests" module is used for releases only.
'checkout_requests': False,
'mac_xcode_version': 'default',
# To allow running hooks without parsing the DEPS tree
'process_deps': True,
@@ -104,18 +104,6 @@ deps = {
'url': Var('requests_git') + '/requests.git' + '@' + Var('requests_version'),
'condition': 'checkout_requests and process_deps',
},
'src/third_party/squirrel.mac': {
'url': Var("squirrel_git") + '/Squirrel.Mac.git@' + Var("squirrel.mac_version"),
'condition': 'process_deps',
},
'src/third_party/squirrel.mac/vendor/ReactiveObjC': {
'url': 'https://github.com/ReactiveCocoa/ReactiveObjC.git@74ab5baccc6f7202c8ac69a8d1e152c29dc1ea76',
'condition': 'process_deps'
},
'src/third_party/squirrel.mac/vendor/Mantle': {
'url': 'https://github.com/Mantle/Mantle.git@78d3966b3c331292ea29ec38661b25df0a245948',
'condition': 'process_deps',
}
}
hooks = [
@@ -124,7 +112,7 @@ hooks = [
'condition': '(checkout_chromium and apply_patches) and process_deps',
'pattern': 'src/electron',
'action': [
'python3',
'python',
'src/electron/script/apply_all_patches.py',
'src/electron/patches/config.json',
],
@@ -142,7 +130,7 @@ hooks = [
'name': 'electron_npm_deps',
'pattern': 'src/electron/package.json',
'action': [
'python3',
'python',
'-c',
'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python", "script/lib/npx.py", "yarn@' + (Var("yarn_version")) + '", "install", "--frozen-lockfile"]);',
],
@@ -152,7 +140,7 @@ hooks = [
'pattern': 'src/electron',
'condition': 'checkout_boto and process_deps',
'action': [
'python3',
'python',
'-c',
'import os, subprocess; os.chdir(os.path.join("src", "electron", "vendor", "boto")); subprocess.check_call(["python", "setup.py", "build"]);',
],
@@ -162,7 +150,7 @@ hooks = [
'pattern': 'src/electron',
'condition': 'checkout_requests and process_deps',
'action': [
'python3',
'python',
'-c',
'import os, subprocess; os.chdir(os.path.join("src", "electron", "vendor", "requests")); subprocess.check_call(["python", "setup.py", "build"]);',
],
@@ -171,5 +159,4 @@ hooks = [
recursedeps = [
'src',
'src/third_party/squirrel.mac',
]

View File

@@ -1 +1 @@
11.0.0-nightly.20200709
10.0.0-beta.11

View File

@@ -29,7 +29,7 @@
version: 1.0.{build}
build_cloud: electron-16-core
image: vs2019bt-16.4.0
image: vs2019bt-16.6.2
environment:
GIT_CACHE_PATH: C:\Users\electron\libcc_cache
ELECTRON_OUT_DIR: Default

View File

@@ -1,16 +0,0 @@
#!/usr/bin/env python
import os
import subprocess
import sys
source = sys.argv[1]
dest = sys.argv[2]
# Ensure any existing framework is removed
subprocess.check_output(["rm", "-rf", dest])
subprocess.check_output(["cp", "-a", source, dest])
# Strip headers, we do not need to ship them
subprocess.check_output(["rm", "-r", os.path.join(dest, 'Headers')])
subprocess.check_output(["rm", "-r", os.path.join(dest, 'Versions', 'Current', 'Headers')])

View File

@@ -93,6 +93,14 @@ static_library("chrome") {
]
}
if (is_win) {
sources += [
"//chrome/browser/win/icon_reader_service.cc",
"//chrome/browser/win/icon_reader_service.h",
]
public_deps += [ "//chrome/services/util_win:lib" ]
}
if (enable_desktop_capturer) {
sources += [
"//chrome/browser/media/webrtc/desktop_media_list.h",
@@ -153,13 +161,6 @@ static_library("chrome") {
}
}
if (enable_tts) {
sources += [
"//chrome/browser/speech/tts_controller_delegate_impl.cc",
"//chrome/browser/speech/tts_controller_delegate_impl.h",
]
}
if (enable_widevine) {
sources += [
"//chrome/renderer/media/chrome_key_systems.cc",

View File

@@ -1,9 +1,8 @@
import * as electron from 'electron';
import { app, dialog } from 'electron';
import * as fs from 'fs';
import * as path from 'path';
import * as url from 'url';
const { app, dialog } = electron;
type DefaultAppOptions = {
file: null | string;
@@ -146,90 +145,13 @@ function startRepl () {
process.exit(1);
}
// Prevent quitting.
// prevent quitting
app.on('window-all-closed', () => {});
const GREEN = '32';
const colorize = (color: string, s: string) => `\x1b[${color}m${s}\x1b[0m`;
const electronVersion = colorize(GREEN, `v${process.versions.electron}`);
const nodeVersion = colorize(GREEN, `v${process.versions.node}`);
console.info(`
Welcome to the Electron.js REPL \\[._.]/
You can access all Electron.js modules here as well as Node.js modules.
Using: Node.js ${nodeVersion} and Electron.js ${electronVersion}
`);
const { REPLServer } = require('repl');
const repl = new REPLServer({
prompt: '> '
}).on('exit', () => {
const repl = require('repl');
repl.start('> ').on('exit', () => {
process.exit(0);
});
function defineBuiltin (context: any, name: string, getter: Function) {
const setReal = (val: any) => {
// Deleting the property before re-assigning it disables the
// getter/setter mechanism.
delete context[name];
context[name] = val;
};
Object.defineProperty(context, name, {
get: () => {
const lib = getter();
delete context[name];
Object.defineProperty(context, name, {
get: () => lib,
set: setReal,
configurable: true,
enumerable: false
});
return lib;
},
set: setReal,
configurable: true,
enumerable: false
});
}
defineBuiltin(repl.context, 'electron', () => electron);
for (const api of Object.keys(electron) as (keyof typeof electron)[]) {
defineBuiltin(repl.context, api, () => electron[api]);
}
// Copied from node/lib/repl.js. For better DX, we don't want to
// show e.g 'contentTracing' at a higher priority than 'const', so
// we only trigger custom tab-completion when no common words are
// potentially matches.
const commonWords = [
'async', 'await', 'break', 'case', 'catch', 'const', 'continue',
'debugger', 'default', 'delete', 'do', 'else', 'export', 'false',
'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'let',
'new', 'null', 'return', 'switch', 'this', 'throw', 'true', 'try',
'typeof', 'var', 'void', 'while', 'with', 'yield'
];
const electronBuiltins = [...Object.keys(electron), 'original-fs', 'electron'];
const defaultComplete = repl.completer;
repl.completer = (line: string, callback: Function) => {
const lastSpace = line.lastIndexOf(' ');
const currentSymbol = line.substring(lastSpace + 1, repl.cursor);
const filterFn = (c: string) => c.startsWith(currentSymbol);
const ignores = commonWords.filter(filterFn);
const hits = electronBuiltins.filter(filterFn);
if (!ignores.length && hits.length) {
callback(null, [hits, currentSymbol]);
} else {
defaultComplete.apply(repl, [line, callback]);
}
};
}
// Start the specified app if there is one specified in command line, otherwise

View File

@@ -92,6 +92,7 @@ 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

@@ -140,16 +140,6 @@ this event, such as launching the application for the first time, attempting
to re-launch the application when it's already running, or clicking on the
application's dock or taskbar icon.
### Event: 'did-become-active' _macOS_
Returns:
* `event` Event
Emitted when mac application become active. Difference from `activate` event is
that `did-become-active` is emitted every time the app becomes active, not only
when Dock icon is clicked or application is re-launched.
### Event: 'continue-activity' _macOS_
Returns:
@@ -815,20 +805,6 @@ Returns `String` - Name of the application handling the protocol, or an empty
This method returns the application name of the default handler for the protocol
(aka URI scheme) of a URL.
### `app.getApplicationInfoForProtocol(url)` _macOS_ _Windows_
* `url` String - a URL with the protocol name to check. Unlike the other
methods in this family, this accepts an entire URL, including `://` at a
minimum (e.g. `https://`).
Returns `Promise<Object>` - Resolve with an object containing the following:
* `icon` NativeImage - the display icon of the app handling the protocol.
* `path` String - installation path of the app handling the protocol.
* `name` String - display name of the app handling the protocol.
This method returns a promise that contains the application name, icon and path of the default handler for the protocol
(aka URI scheme) of a URL.
### `app.setUserTasks(tasks)` _Windows_
* `tasks` [Task[]](structures/task.md) - Array of `Task` objects
@@ -1246,7 +1222,7 @@ Show the app's about panel options. These options can be overridden with `app.se
* `credits` String (optional) _macOS_ _Windows_ - Credit information.
* `authors` String[] (optional) _Linux_ - List of app authors.
* `website` String (optional) _Linux_ - The app's website.
* `iconPath` String (optional) _Linux_ _Windows_ - Path to the app's icon in a JPEG or PNG file format. On Linux, will be shown as 64x64 pixels while retaining aspect ratio.
* `iconPath` String (optional) _Linux_ _Windows_ - Path to the app's icon. On Linux, will be shown as 64x64 pixels while retaining aspect ratio.
Set the about panel options. This will override the values defined in the app's `.plist` file on macOS. See the [Apple docs][about-panel-options] for more details. On Linux, values must be set in order to be shown; there are no defaults.

View File

@@ -692,7 +692,7 @@ Returns `BrowserWindow | null` - The window that owns the given `browserView`. I
* `id` Integer
Returns `BrowserWindow | null` - The window with the given `id`.
Returns `BrowserWindow` - The window with the given `id`.
#### `BrowserWindow.addExtension(path)` _Deprecated_

View File

@@ -72,50 +72,6 @@ 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:
@@ -138,15 +94,6 @@ 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

@@ -96,7 +96,7 @@ Appends the `menuItem` to the menu.
* `id` String
Returns `MenuItem | null` the item with the specified `id`
Returns `MenuItem` the item with the specified `id`
#### `menu.insert(pos, menuItem)`

View File

@@ -8,11 +8,11 @@ Process: [Main](../glossary.md#main-process)
The `powerMonitor` module emits the following events:
### Event: 'suspend'
### Event: 'suspend' _Linux_ _Windows_
Emitted when the system is suspending.
### Event: 'resume'
### Event: 'resume' _Linux_ _Windows_
Emitted when system is resuming.

View File

@@ -63,8 +63,8 @@ The `protocol` module has the following methods:
module gets emitted and can be called only once.
Registers the `scheme` as standard, secure, bypasses content security policy for
resources, allows registering ServiceWorker, supports fetch API, and streaming
video/audio. Specify a privilege with the value of `true` to enable the capability.
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:
@@ -103,11 +103,6 @@ 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.
Protocols that use streams (http and stream protocols) should set `stream: true`.
The `<video>` and `<audio>` HTML elements expect protocols to buffer their
responses by default. The `stream` flag configures those elements to correctly
expect streaming responses.
### `protocol.registerFileProtocol(scheme, handler)`
* `scheme` String

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

@@ -8,4 +8,3 @@
* `allowServiceWorkers` Boolean (optional) - Default false.
* `supportFetchAPI` Boolean (optional) - Default false.
* `corsEnabled` Boolean (optional) - Default false.
* `stream` Boolean (optional) - Default false.

View File

@@ -11,8 +11,6 @@
* `Pepper Plugin`
* `Pepper Plugin Broker`
* `Unknown`
* `name` String (optional) - The name of the process. i.e. for plugins it might be Flash.
Examples for utility: `Audio Service`, `Content Decryption Module Service`, `Network Service`, `Video Capture`, etc.
* `cpu` [CPUUsage](cpu-usage.md) - CPU usage of the process.
* `creationTime` Number - Creation time for this process.
The time is represented as number of milliseconds since epoch.

View File

@@ -6,7 +6,7 @@
* `trace_buffer_size_in_events` number (optional) - maximum size of the trace
recording buffer in events.
* `enable_argument_filter` boolean (optional) - if true, filter event data
according to a specific list of events that have been manually vetted to not
according to a whitelist of events that have been manually vetted to not
include any PII. See [the implementation in
Chromium][trace_event_args_whitelist.cc] for specifics.
* `included_categories` String[] (optional) - a list of tracing categories to

View File

@@ -738,9 +738,9 @@ Emitted when a `<webview>` has been attached to this web contents.
Returns:
* `event` Event
* `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
* `level` Integer
* `message` String
* `line` Integer
* `sourceId` String
Emitted when the associated window logs a console message.
@@ -1371,6 +1371,8 @@ An example of `webContents.printToPDF`:
```javascript
const { BrowserWindow } = require('electron')
const fs = require('fs')
const path = require('path')
const os = require('os')
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')
@@ -1378,12 +1380,13 @@ win.loadURL('http://github.com')
win.webContents.on('did-finish-load', () => {
// Use default printing options
win.webContents.printToPDF({}).then(data => {
fs.writeFile('/tmp/print.pdf', data, (error) => {
const pdfPath = path.join(os.homedir(), 'Desktop', 'temp.pdf')
fs.writeFile(pdfPath, data, (error) => {
if (error) throw error
console.log('Write PDF successfully.')
console.log(`Wrote PDF successfully to ${pdfPath}`)
})
}).catch(error => {
console.log(error)
console.log(`Failed to write PDF to ${pdfPath}: `, error)
})
})
```

View File

@@ -755,9 +755,9 @@ Fired when page leaves fullscreen triggered by HTML API.
Returns:
* `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
* `level` Integer
* `message` String
* `line` Integer
* `sourceId` String
Fired when the guest window logs a console message.

View File

@@ -14,15 +14,6 @@ This document uses the following convention to categorize breaking changes:
## Planned Breaking API Changes (12.0)
### Default Changed: `contextIsolation` defaults to `true`
In Electron 12, `contextIsolation` will be enabled by default. To restore
the previous behavior, `contextIsolation: false` must be specified in WebPreferences.
We [recommend having contextIsolation enabled](https://github.com/electron/electron/blob/master/docs/tutorial/security.md#3-enable-context-isolation-for-remote-content) for the security of your application.
For more details see: https://github.com/electron/electron/issues/23506
### Removed: `crashReporter` methods in the renderer process
The following `crashReporter` methods are no longer available in the renderer

View File

@@ -23,3 +23,4 @@ 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

@@ -10,10 +10,6 @@ Check the build prerequisites for your platform before proceeding
* [Linux](build-instructions-linux.md#prerequisites)
* [Windows](build-instructions-windows.md#prerequisites)
## Build Tools
[Electron's Build Tools](https://github.com/electron/build-tools) automate much of the setup for compiling Electron from source with different configurations and build targets. If you wish to set up the environment manually, the instructions are listed below.
## GN prerequisites
You'll need to install [`depot_tools`][depot-tools], the toolset

View File

@@ -0,0 +1,121 @@
# 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

@@ -0,0 +1,3 @@
# 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

@@ -100,25 +100,6 @@ To see all of this in action, check out Electron Fiddle's source code,
[especially its `electron-forge` configuration
file](https://github.com/electron/fiddle/blob/master/forge.config.js).
If you plan to access the microphone or camera within your app using Electron's APIs, you'll also
need to add the following entitlements:
```xml
<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
```
If these are not present in your app's entitlements when you invoke, for example:
```js
const { systemPreferences } = require('electron')
const microphone = systemPreferences.askForMediaAccess('microphone')
```
Your app may crash. See the Resource Access section in [Hardened Runtime](https://developer.apple.com/documentation/security/hardened_runtime) for more information and entitlements you may need.
## `electron-builder`

View File

@@ -87,7 +87,7 @@ e.g. `2.0.1`.
Specifically, the above means:
1. Admitting non-breaking-API changes before Week 3 in the beta cycle is okay, even if those changes have the potential to cause moderate side-effects
1. Admitting non-breaking-API changes before Week 3 in the beta cycle is okay, even if those changes have the potential to cause moderate side-affects
2. Admitting feature-flagged changes, that do not otherwise alter existing code paths, at most points in the beta cycle is okay. Users can explicitly enable those flags in their apps.
3. Admitting features of any sort after Week 3 in the beta cycle is 👎 without a very good reason.
@@ -139,7 +139,7 @@ We seek to increase clarity at all levels of the update and releases process. St
* Commits that would result in a semver **minor** bump must start with `feat:`.
* Commits that would result in a semver **patch** bump must start with `fix:`.
* We allow squashing of commits, provided that the squashed message adheres to the above message format.
* We allow squashing of commits, provided that the squashed message adheres the the above message format.
* It is acceptable for some commits in a pull request to not include a semantic prefix, as long as the pull request title contains a meaningful encompassing semantic message.
# Versioned `master`

View File

@@ -44,10 +44,23 @@ 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).
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:
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
{
"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.
```json
{
@@ -141,10 +154,10 @@ function createWindow () {
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}

View File

@@ -75,4 +75,9 @@
<message name="IDS_ACCEPT_LANGUAGES" use_name_for_id="true">
en-US,en
</message>
<if expr="is_win">
<message name="IDS_UTILITY_PROCESS_UTILITY_WIN_NAME" desc="The name of the utility process used to handle Windows utility operations.">
Windows Utilities
</message>
</if>
</grit-part>

View File

@@ -135,12 +135,13 @@ auto_filenames = {
sandbox_bundle_deps = [
"lib/browser/api/module-names.ts",
"lib/common/api/clipboard.ts",
"lib/common/api/clipboard.js",
"lib/common/api/deprecate.ts",
"lib/common/api/module-list.ts",
"lib/common/api/native-image.ts",
"lib/common/api/shell.ts",
"lib/common/api/native-image.js",
"lib/common/api/shell.js",
"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",
@@ -148,7 +149,7 @@ auto_filenames = {
"lib/renderer/api/crash-reporter.ts",
"lib/renderer/api/desktop-capturer.ts",
"lib/renderer/api/ipc-renderer.ts",
"lib/renderer/api/remote.ts",
"lib/renderer/api/remote.js",
"lib/renderer/api/web-frame.ts",
"lib/renderer/inspector.ts",
"lib/renderer/ipc-renderer-internal-utils.ts",
@@ -165,65 +166,62 @@ 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.ts",
"lib/sandboxed_renderer/init.js",
"package.json",
"tsconfig.electron.json",
"tsconfig.json",
"typings/internal-ambient.d.ts",
"typings/internal-electron.d.ts",
]
isolated_bundle_deps = [
"lib/common/electron-binding-setup.ts",
"lib/isolated_renderer/init.js",
"lib/renderer/web-view/web-view-constants.ts",
"lib/renderer/web-view/web-view-element.ts",
"package.json",
"tsconfig.electron.json",
"tsconfig.json",
"typings/internal-ambient.d.ts",
"typings/internal-electron.d.ts",
]
browser_bundle_deps = [
"lib/browser/api/app.ts",
"lib/browser/api/auto-updater.ts",
"lib/browser/api/auto-updater/auto-updater-native.ts",
"lib/browser/api/auto-updater/auto-updater-win.ts",
"lib/browser/api/auto-updater/squirrel-update-win.ts",
"lib/browser/api/base-window.ts",
"lib/browser/api/browser-view.ts",
"lib/browser/api/browser-window.ts",
"lib/browser/api/content-tracing.ts",
"lib/browser/api/auto-updater.js",
"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-window.js",
"lib/browser/api/content-tracing.js",
"lib/browser/api/crash-reporter.ts",
"lib/browser/api/desktop-capturer.ts",
"lib/browser/api/dialog.ts",
"lib/browser/api/dialog.js",
"lib/browser/api/exports/electron.ts",
"lib/browser/api/global-shortcut.ts",
"lib/browser/api/in-app-purchase.ts",
"lib/browser/api/global-shortcut.js",
"lib/browser/api/in-app-purchase.js",
"lib/browser/api/ipc-main.ts",
"lib/browser/api/menu-item-roles.ts",
"lib/browser/api/menu-item.ts",
"lib/browser/api/menu-utils.ts",
"lib/browser/api/menu.ts",
"lib/browser/api/menu-item-roles.js",
"lib/browser/api/menu-item.js",
"lib/browser/api/menu-utils.js",
"lib/browser/api/menu.js",
"lib/browser/api/message-channel.ts",
"lib/browser/api/module-list.ts",
"lib/browser/api/native-theme.ts",
"lib/browser/api/net-log.ts",
"lib/browser/api/net-log.js",
"lib/browser/api/net.ts",
"lib/browser/api/notification.ts",
"lib/browser/api/notification.js",
"lib/browser/api/power-monitor.ts",
"lib/browser/api/power-save-blocker.ts",
"lib/browser/api/power-save-blocker.js",
"lib/browser/api/protocol.ts",
"lib/browser/api/screen.ts",
"lib/browser/api/session.ts",
"lib/browser/api/session.js",
"lib/browser/api/system-preferences.ts",
"lib/browser/api/top-level-window.js",
"lib/browser/api/touch-bar.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.ts",
"lib/browser/chrome-extension-shim.ts",
"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/web-contents.js",
"lib/browser/chrome-extension-shim.js",
"lib/browser/default-menu.ts",
"lib/browser/desktop-capturer.ts",
"lib/browser/devtools.ts",
@@ -234,17 +232,18 @@ auto_filenames = {
"lib/browser/ipc-main-internal-utils.ts",
"lib/browser/ipc-main-internal.ts",
"lib/browser/message-port-main.ts",
"lib/browser/navigation-controller.ts",
"lib/browser/navigation-controller.js",
"lib/browser/remote/objects-registry.ts",
"lib/browser/remote/server.ts",
"lib/browser/rpc-server.ts",
"lib/browser/rpc-server.js",
"lib/browser/utils.ts",
"lib/common/api/clipboard.ts",
"lib/common/api/clipboard.js",
"lib/common/api/deprecate.ts",
"lib/common/api/module-list.ts",
"lib/common/api/native-image.ts",
"lib/common/api/shell.ts",
"lib/common/api/native-image.js",
"lib/common/api/shell.js",
"lib/common/define-properties.ts",
"lib/common/electron-binding-setup.ts",
"lib/common/init.ts",
"lib/common/parse-features-string.ts",
"lib/common/reset-search-paths.ts",
@@ -256,18 +255,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-names.ts",
"lib/common/api/clipboard.ts",
"lib/common/api/clipboard.js",
"lib/common/api/deprecate.ts",
"lib/common/api/module-list.ts",
"lib/common/api/native-image.ts",
"lib/common/api/shell.ts",
"lib/common/api/native-image.js",
"lib/common/api/shell.js",
"lib/common/define-properties.ts",
"lib/common/electron-binding-setup.ts",
"lib/common/init.ts",
"lib/common/reset-search-paths.ts",
"lib/common/type-utils.ts",
@@ -279,7 +277,7 @@ auto_filenames = {
"lib/renderer/api/exports/electron.ts",
"lib/renderer/api/ipc-renderer.ts",
"lib/renderer/api/module-list.ts",
"lib/renderer/api/remote.ts",
"lib/renderer/api/remote.js",
"lib/renderer/api/web-frame.ts",
"lib/renderer/init.ts",
"lib/renderer/inspector.ts",
@@ -299,18 +297,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-names.ts",
"lib/common/api/clipboard.ts",
"lib/common/api/clipboard.js",
"lib/common/api/deprecate.ts",
"lib/common/api/module-list.ts",
"lib/common/api/native-image.ts",
"lib/common/api/shell.ts",
"lib/common/api/native-image.js",
"lib/common/api/shell.js",
"lib/common/define-properties.ts",
"lib/common/electron-binding-setup.ts",
"lib/common/init.ts",
"lib/common/reset-search-paths.ts",
"lib/common/type-utils.ts",
@@ -321,7 +318,7 @@ auto_filenames = {
"lib/renderer/api/exports/electron.ts",
"lib/renderer/api/ipc-renderer.ts",
"lib/renderer/api/module-list.ts",
"lib/renderer/api/remote.ts",
"lib/renderer/api/remote.js",
"lib/renderer/api/web-frame.ts",
"lib/renderer/ipc-renderer-internal-utils.ts",
"lib/renderer/ipc-renderer-internal.ts",
@@ -331,7 +328,5 @@ auto_filenames = {
"package.json",
"tsconfig.electron.json",
"tsconfig.json",
"typings/internal-ambient.d.ts",
"typings/internal-electron.d.ts",
]
}

View File

@@ -44,8 +44,6 @@ filenames = {
"shell/browser/api/electron_api_app_mac.mm",
"shell/browser/api/electron_api_auto_updater.cc",
"shell/browser/api/electron_api_auto_updater.h",
"shell/browser/api/electron_api_base_window.cc",
"shell/browser/api/electron_api_base_window.h",
"shell/browser/api/electron_api_browser_view.cc",
"shell/browser/api/electron_api_browser_view.h",
"shell/browser/api/electron_api_browser_window.cc",
@@ -104,6 +102,8 @@ filenames = {
"shell/browser/api/electron_api_system_preferences.h",
"shell/browser/api/electron_api_system_preferences_mac.mm",
"shell/browser/api/electron_api_system_preferences_win.cc",
"shell/browser/api/electron_api_top_level_window.cc",
"shell/browser/api/electron_api_top_level_window.h",
"shell/browser/api/electron_api_tray.cc",
"shell/browser/api/electron_api_tray.h",
"shell/browser/api/electron_api_url_loader.cc",

View File

@@ -4,8 +4,8 @@ import * as path from 'path';
import { deprecate, Menu } from 'electron';
import { EventEmitter } from 'events';
const bindings = process._linkedBinding('electron_browser_app');
const commandLine = process._linkedBinding('electron_common_command_line');
const bindings = process.electronBinding('app');
const commandLine = process.electronBinding('command_line');
const { app, App } = bindings;
// Only one app object permitted.

View File

@@ -0,0 +1,7 @@
'use strict';
if (process.platform === 'win32') {
module.exports = require('@electron/internal/browser/api/auto-updater/auto-updater-win');
} else {
module.exports = require('@electron/internal/browser/api/auto-updater/auto-updater-native');
}

View File

@@ -1,5 +0,0 @@
if (process.platform === 'win32') {
module.exports = require('./auto-updater/auto-updater-win');
} else {
module.exports = require('./auto-updater/auto-updater-native');
}

View File

@@ -0,0 +1,10 @@
'use strict';
const EventEmitter = require('events').EventEmitter;
const { autoUpdater, AutoUpdater } = process.electronBinding('auto_updater');
// AutoUpdater is an EventEmitter.
Object.setPrototypeOf(AutoUpdater.prototype, EventEmitter.prototype);
EventEmitter.call(autoUpdater);
module.exports = autoUpdater;

View File

@@ -1,8 +0,0 @@
import { EventEmitter } from 'events';
const { autoUpdater, AutoUpdater } = process._linkedBinding('electron_browser_auto_updater');
// AutoUpdater is an EventEmitter.
Object.setPrototypeOf(AutoUpdater.prototype, EventEmitter.prototype);
EventEmitter.call(autoUpdater);
export default autoUpdater;

View File

@@ -1,14 +1,13 @@
import { app } from 'electron';
import { EventEmitter } from 'events';
import * as squirrelUpdate from './squirrel-update-win';
'use strict';
const { app } = require('electron');
const { EventEmitter } = require('events');
const squirrelUpdate = require('@electron/internal/browser/api/auto-updater/squirrel-update-win');
class AutoUpdater extends EventEmitter {
updateAvailable: boolean = false;
updateURL: string | null = null;
quitAndInstall () {
if (!this.updateAvailable) {
return this.emitError(new Error('No update available, can\'t quit and install'));
return this.emitError('No update available, can\'t quit and install');
}
squirrelUpdate.processStart();
app.quit();
@@ -18,8 +17,8 @@ class AutoUpdater extends EventEmitter {
return this.updateURL;
}
setFeedURL (options: { url: string } | string) {
let updateURL: string;
setFeedURL (options) {
let updateURL;
if (typeof options === 'object') {
if (typeof options.url === 'string') {
updateURL = options.url;
@@ -35,15 +34,14 @@ class AutoUpdater extends EventEmitter {
}
checkForUpdates () {
const url = this.updateURL;
if (!url) {
return this.emitError(new Error('Update URL is not set'));
if (!this.updateURL) {
return this.emitError('Update URL is not set');
}
if (!squirrelUpdate.supported()) {
return this.emitError(new Error('Can not find Squirrel'));
return this.emitError('Can not find Squirrel');
}
this.emit('checking-for-update');
squirrelUpdate.checkForUpdate(url, (error, update) => {
squirrelUpdate.checkForUpdate(this.updateURL, (error, update) => {
if (error != null) {
return this.emitError(error);
}
@@ -52,7 +50,7 @@ class AutoUpdater extends EventEmitter {
}
this.updateAvailable = true;
this.emit('update-available');
squirrelUpdate.update(url, (error) => {
squirrelUpdate.update(this.updateURL, (error) => {
if (error != null) {
return this.emitError(error);
}
@@ -68,9 +66,9 @@ class AutoUpdater extends EventEmitter {
// Private: Emit both error object and message, this is to keep compatibility
// with Old APIs.
emitError (error: Error) {
this.emit('error', error, error.message);
emitError (message) {
this.emit('error', new Error(message), message);
}
}
export default new AutoUpdater();
module.exports = new AutoUpdater();

View File

@@ -1,6 +1,8 @@
import * as fs from 'fs';
import * as path from 'path';
import { spawn, ChildProcessWithoutNullStreams } from 'child_process';
'use strict';
const fs = require('fs');
const path = require('path');
const spawn = require('child_process').spawn;
// i.e. my-app/app-0.1.13/
const appFolder = path.dirname(process.execPath);
@@ -8,15 +10,15 @@ const appFolder = path.dirname(process.execPath);
// i.e. my-app/Update.exe
const updateExe = path.resolve(appFolder, '..', 'Update.exe');
const exeName = path.basename(process.execPath);
let spawnedArgs: string[] = [];
let spawnedProcess: ChildProcessWithoutNullStreams | undefined;
let spawnedArgs = [];
let spawnedProcess;
const isSameArgs = (args: string[]) => args.length === spawnedArgs.length && args.every((e, i) => e === spawnedArgs[i]);
const isSameArgs = (args) => args.length === spawnedArgs.length && args.every((e, i) => e === spawnedArgs[i]);
// Spawn a command and invoke the callback when it completes with an error
// and the output from standard out.
const spawnUpdate = function (args: string[], detached: boolean, callback: Function) {
let error: Error, errorEmitted: boolean, stderr: string, stdout: string;
const spawnUpdate = function (args, detached, callback) {
let error, errorEmitted, stderr, stdout;
try {
// Ensure we don't spawn multiple squirrel processes
@@ -77,13 +79,13 @@ const spawnUpdate = function (args: string[], detached: boolean, callback: Funct
};
// Start an instance of the installed app.
export function processStart () {
exports.processStart = function () {
return spawnUpdate(['--processStartAndWait', exeName], true, function () {});
}
};
// Download the releases specified by the URL and write new results to stdout.
export function checkForUpdate (updateURL: string, callback: (error: Error | null, update?: any) => void) {
return spawnUpdate(['--checkForUpdate', updateURL], false, function (error: Error, stdout: string) {
exports.checkForUpdate = function (updateURL, callback) {
return spawnUpdate(['--checkForUpdate', updateURL], false, function (error, stdout) {
let ref, ref1, update;
if (error != null) {
return callback(error);
@@ -91,27 +93,27 @@ export function checkForUpdate (updateURL: string, callback: (error: Error | nul
try {
// Last line of output is the JSON details about the releases
const json = stdout.trim().split('\n').pop();
update = (ref = JSON.parse(json!)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : undefined : undefined : undefined;
update = (ref = JSON.parse(json)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : undefined : undefined : undefined;
} catch {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(new Error(`Invalid result:\n${stdout}`));
return callback(`Invalid result:\n${stdout}`);
}
return callback(null, update);
});
}
};
// Update the application to the latest remote version specified by URL.
export function update (updateURL: string, callback: (error: Error) => void) {
exports.update = function (updateURL, callback) {
return spawnUpdate(['--update', updateURL], false, callback);
}
};
// Is the Update.exe installed with the current application?
export function supported () {
exports.supported = function () {
try {
fs.accessSync(updateExe, fs.constants.R_OK);
fs.accessSync(updateExe, fs.R_OK);
return true;
} catch {
return false;
}
}
};

View File

@@ -0,0 +1,16 @@
'use strict';
const { EventEmitter } = require('events');
const { BrowserView } = process.electronBinding('browser_view');
Object.setPrototypeOf(BrowserView.prototype, EventEmitter.prototype);
BrowserView.fromWebContents = (webContents) => {
for (const view of BrowserView.getAllViews()) {
if (view.webContents.equal(webContents)) return view;
}
return null;
};
module.exports = BrowserView;

View File

@@ -1,15 +0,0 @@
import { EventEmitter } from 'events';
const { BrowserView } = process._linkedBinding('electron_browser_browser_view');
Object.setPrototypeOf(BrowserView.prototype, EventEmitter.prototype);
BrowserView.fromWebContents = (webContents: Electron.WebContents) => {
for (const view of BrowserView.getAllViews()) {
if (view.webContents.equal(webContents)) return view;
}
return null;
};
export default BrowserView;

View File

@@ -0,0 +1,168 @@
'use strict';
const electron = require('electron');
const { TopLevelWindow, deprecate } = electron;
const { BrowserWindow } = process.electronBinding('window');
Object.setPrototypeOf(BrowserWindow.prototype, TopLevelWindow.prototype);
BrowserWindow.prototype._init = function () {
// Call parent class's _init.
TopLevelWindow.prototype._init.call(this);
// Avoid recursive require.
const { app } = electron;
const nativeSetBounds = this.setBounds;
this.setBounds = (bounds, ...opts) => {
bounds = {
...this.getBounds(),
...bounds
};
nativeSetBounds.call(this, bounds, ...opts);
};
// Sometimes the webContents doesn't get focus when window is shown, so we
// have to force focusing on webContents in this case. The safest way is to
// focus it when we first start to load URL, if we do it earlier it won't
// have effect, if we do it later we might move focus in the page.
//
// Though this hack is only needed on macOS when the app is launched from
// Finder, we still do it on all platforms in case of other bugs we don't
// know.
this.webContents.once('load-url', function () {
this.focus();
});
// Redirect focus/blur event to app instance too.
this.on('blur', (event) => {
app.emit('browser-window-blur', event, this);
});
this.on('focus', (event) => {
app.emit('browser-window-focus', event, this);
});
// Subscribe to visibilityState changes and pass to renderer process.
let isVisible = this.isVisible() && !this.isMinimized();
const visibilityChanged = () => {
const newState = this.isVisible() && !this.isMinimized();
if (isVisible !== newState) {
isVisible = newState;
const visibilityState = isVisible ? 'visible' : 'hidden';
this.webContents.emit('-window-visibility-change', visibilityState);
}
};
const visibilityEvents = ['show', 'hide', 'minimize', 'maximize', 'restore'];
for (const event of visibilityEvents) {
this.on(event, visibilityChanged);
}
// Notify the creation of the window.
const event = process.electronBinding('event').createEmpty();
app.emit('browser-window-created', event, this);
Object.defineProperty(this, 'devToolsWebContents', {
enumerable: true,
configurable: false,
get () {
return this.webContents.devToolsWebContents;
}
});
};
const isBrowserWindow = (win) => {
return win && win.constructor.name === 'BrowserWindow';
};
BrowserWindow.fromId = (id) => {
const win = TopLevelWindow.fromId(id);
return isBrowserWindow(win) ? win : null;
};
BrowserWindow.getAllWindows = () => {
return TopLevelWindow.getAllWindows().filter(isBrowserWindow);
};
BrowserWindow.getFocusedWindow = () => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.isFocused() || window.isDevToolsFocused()) return window;
}
return null;
};
BrowserWindow.fromWebContents = (webContents) => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.webContents && window.webContents.equal(webContents)) return window;
}
return null;
};
BrowserWindow.fromBrowserView = (browserView) => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.getBrowserView() === browserView) return window;
}
return null;
};
// Helpers.
Object.assign(BrowserWindow.prototype, {
loadURL (...args) {
return this.webContents.loadURL(...args);
},
getURL (...args) {
return this.webContents.getURL();
},
loadFile (...args) {
return this.webContents.loadFile(...args);
},
reload (...args) {
return this.webContents.reload(...args);
},
send (...args) {
return this.webContents.send(...args);
},
openDevTools (...args) {
return this.webContents.openDevTools(...args);
},
closeDevTools () {
return this.webContents.closeDevTools();
},
isDevToolsOpened () {
return this.webContents.isDevToolsOpened();
},
isDevToolsFocused () {
return this.webContents.isDevToolsFocused();
},
toggleDevTools () {
return this.webContents.toggleDevTools();
},
inspectElement (...args) {
return this.webContents.inspectElement(...args);
},
inspectSharedWorker () {
return this.webContents.inspectSharedWorker();
},
inspectServiceWorker () {
return this.webContents.inspectServiceWorker();
},
showDefinitionForSelection () {
return this.webContents.showDefinitionForSelection();
},
capturePage (...args) {
return this.webContents.capturePage(...args);
},
setTouchBar (touchBar) {
electron.TouchBar._setOnWindow(touchBar, this);
},
getBackgroundThrottling () {
return this.webContents.getBackgroundThrottling();
},
setBackgroundThrottling (allowed) {
this.webContents.setBackgroundThrottling(allowed);
}
});
module.exports = BrowserWindow;

View File

@@ -1,182 +0,0 @@
import { BaseWindow, WebContents, Event, BrowserView, TouchBar } from 'electron';
import type { BrowserWindow as BWT } from 'electron';
const { BrowserWindow } = process._linkedBinding('electron_browser_window') as { BrowserWindow: typeof BWT };
Object.setPrototypeOf(BrowserWindow.prototype, BaseWindow.prototype);
(BrowserWindow.prototype as any)._init = function (this: BWT) {
// Call parent class's _init.
(BaseWindow.prototype as any)._init.call(this);
// Avoid recursive require.
const { app } = require('electron');
const nativeSetBounds = this.setBounds;
this.setBounds = (bounds, ...opts) => {
bounds = {
...this.getBounds(),
...bounds
};
nativeSetBounds.call(this, bounds, ...opts);
};
// Sometimes the webContents doesn't get focus when window is shown, so we
// have to force focusing on webContents in this case. The safest way is to
// focus it when we first start to load URL, if we do it earlier it won't
// have effect, if we do it later we might move focus in the page.
//
// Though this hack is only needed on macOS when the app is launched from
// Finder, we still do it on all platforms in case of other bugs we don't
// know.
this.webContents.once('load-url' as any, function (this: WebContents) {
this.focus();
});
// Redirect focus/blur event to app instance too.
this.on('blur', (event: Event) => {
app.emit('browser-window-blur', event, this);
});
this.on('focus', (event: Event) => {
app.emit('browser-window-focus', event, this);
});
// Subscribe to visibilityState changes and pass to renderer process.
let isVisible = this.isVisible() && !this.isMinimized();
const visibilityChanged = () => {
const newState = this.isVisible() && !this.isMinimized();
if (isVisible !== newState) {
isVisible = newState;
const visibilityState = isVisible ? 'visible' : 'hidden';
this.webContents.emit('-window-visibility-change', visibilityState);
}
};
const visibilityEvents = ['show', 'hide', 'minimize', 'maximize', 'restore'];
for (const event of visibilityEvents) {
this.on(event as any, visibilityChanged);
}
// Notify the creation of the window.
const event = process._linkedBinding('electron_browser_event').createEmpty();
app.emit('browser-window-created', event, this);
Object.defineProperty(this, 'devToolsWebContents', {
enumerable: true,
configurable: false,
get () {
return this.webContents.devToolsWebContents;
}
});
};
const isBrowserWindow = (win: any) => {
return win && win.constructor.name === 'BrowserWindow';
};
BrowserWindow.fromId = (id: number) => {
const win = BaseWindow.fromId(id);
return isBrowserWindow(win) ? win as any as BWT : null;
};
BrowserWindow.getAllWindows = () => {
return BaseWindow.getAllWindows().filter(isBrowserWindow) as any[] as BWT[];
};
BrowserWindow.getFocusedWindow = () => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.isFocused() || window.isDevToolsFocused()) return window;
}
return null;
};
BrowserWindow.fromWebContents = (webContents: WebContents) => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.webContents && window.webContents.equal(webContents)) return window;
}
return null;
};
BrowserWindow.fromBrowserView = (browserView: BrowserView) => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.getBrowserView() === browserView) return window;
}
return null;
};
BrowserWindow.prototype.setTouchBar = function (touchBar) {
(TouchBar as any)._setOnWindow(touchBar, this);
};
// Forwarded to webContents:
BrowserWindow.prototype.loadURL = function (...args) {
return this.webContents.loadURL(...args);
};
BrowserWindow.prototype.getURL = function () {
return this.webContents.getURL();
};
BrowserWindow.prototype.loadFile = function (...args) {
return this.webContents.loadFile(...args);
};
BrowserWindow.prototype.reload = function (...args) {
return this.webContents.reload(...args);
};
BrowserWindow.prototype.send = function (...args) {
return this.webContents.send(...args);
};
BrowserWindow.prototype.openDevTools = function (...args) {
return this.webContents.openDevTools(...args);
};
BrowserWindow.prototype.closeDevTools = function () {
return this.webContents.closeDevTools();
};
BrowserWindow.prototype.isDevToolsOpened = function () {
return this.webContents.isDevToolsOpened();
};
BrowserWindow.prototype.isDevToolsFocused = function () {
return this.webContents.isDevToolsFocused();
};
BrowserWindow.prototype.toggleDevTools = function () {
return this.webContents.toggleDevTools();
};
BrowserWindow.prototype.inspectElement = function (...args) {
return this.webContents.inspectElement(...args);
};
BrowserWindow.prototype.inspectSharedWorker = function () {
return this.webContents.inspectSharedWorker();
};
BrowserWindow.prototype.inspectServiceWorker = function () {
return this.webContents.inspectServiceWorker();
};
BrowserWindow.prototype.showDefinitionForSelection = function () {
return this.webContents.showDefinitionForSelection();
};
BrowserWindow.prototype.capturePage = function (...args) {
return this.webContents.capturePage(...args);
};
BrowserWindow.prototype.getBackgroundThrottling = function () {
return this.webContents.getBackgroundThrottling();
};
BrowserWindow.prototype.setBackgroundThrottling = function (allowed: boolean) {
return this.webContents.setBackgroundThrottling(allowed);
};
module.exports = BrowserWindow;

View File

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

View File

@@ -1 +0,0 @@
export default process._linkedBinding('electron_browser_content_tracing');

View File

@@ -1,6 +1,6 @@
import { app, deprecate } from 'electron';
const binding = process._linkedBinding('electron_browser_crash_reporter');
const binding = process.electronBinding('crash_reporter');
class CrashReporter {
start (options: Electron.CrashReporterStartOptions) {

270
lib/browser/api/dialog.js Normal file
View File

@@ -0,0 +1,270 @@
'use strict';
const { app, BrowserWindow, deprecate } = require('electron');
const binding = process.electronBinding('dialog');
const v8Util = process.electronBinding('v8_util');
const DialogType = {
OPEN: 'OPEN',
SAVE: 'SAVE'
};
const saveFileDialogProperties = {
createDirectory: 1 << 0,
showHiddenFiles: 1 << 1,
treatPackageAsDirectory: 1 << 2,
showOverwriteConfirmation: 1 << 3,
dontAddToRecent: 1 << 4
};
const openFileDialogProperties = {
openFile: 1 << 0,
openDirectory: 1 << 1,
multiSelections: 1 << 2,
createDirectory: 1 << 3, // macOS
showHiddenFiles: 1 << 4,
promptToCreate: 1 << 5, // Windows
noResolveAliases: 1 << 6, // macOS
treatPackageAsDirectory: 1 << 7, // macOS
dontAddToRecent: 1 << 8 // Windows
};
const normalizeAccessKey = (text) => {
if (typeof text !== 'string') return text;
// macOS does not have access keys so remove single ampersands
// and replace double ampersands with a single ampersand
if (process.platform === 'darwin') {
return text.replace(/&(&?)/g, '$1');
}
// Linux uses a single underscore as an access key prefix so escape
// existing single underscores with a second underscore, replace double
// ampersands with a single ampersand, and replace a single ampersand with
// a single underscore
if (process.platform === 'linux') {
return text.replace(/_/g, '__').replace(/&(.?)/g, (match, after) => {
if (after === '&') return after;
return `_${after}`;
});
}
return text;
};
const checkAppInitialized = function () {
if (!app.isReady()) {
throw new Error('dialog module can only be used after app is ready');
}
};
const setupDialogProperties = (type, properties) => {
const dialogPropertiesTypes = (type === DialogType.OPEN) ? openFileDialogProperties : saveFileDialogProperties;
let dialogProperties = 0;
for (const prop in dialogPropertiesTypes) {
if (properties.includes(prop)) {
dialogProperties |= dialogPropertiesTypes[prop];
}
}
return dialogProperties;
};
const saveDialog = (sync, window, options) => {
checkAppInitialized();
if (window && window.constructor !== BrowserWindow) {
options = window;
window = null;
}
if (options == null) options = { title: 'Save' };
const {
buttonLabel = '',
defaultPath = '',
filters = [],
properties = [],
title = '',
message = '',
securityScopedBookmarks = false,
nameFieldLabel = '',
showsTagField = true
} = options;
if (typeof title !== 'string') throw new TypeError('Title must be a string');
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string');
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string');
if (typeof message !== 'string') throw new TypeError('Message must be a string');
if (typeof nameFieldLabel !== 'string') throw new TypeError('Name field label must be a string');
const settings = { buttonLabel, defaultPath, filters, title, message, securityScopedBookmarks, nameFieldLabel, showsTagField, window };
settings.properties = setupDialogProperties(DialogType.SAVE, properties);
return (sync) ? binding.showSaveDialogSync(settings) : binding.showSaveDialog(settings);
};
const openDialog = (sync, window, options) => {
checkAppInitialized();
if (window && window.constructor !== BrowserWindow) {
options = window;
window = null;
}
if (options == null) {
options = {
title: 'Open',
properties: ['openFile']
};
}
const {
buttonLabel = '',
defaultPath = '',
filters = [],
properties = ['openFile'],
title = '',
message = '',
securityScopedBookmarks = false
} = options;
if (!Array.isArray(properties)) throw new TypeError('Properties must be an array');
if (typeof title !== 'string') throw new TypeError('Title must be a string');
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string');
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string');
if (typeof message !== 'string') throw new TypeError('Message must be a string');
const settings = { title, buttonLabel, defaultPath, filters, message, securityScopedBookmarks, window };
settings.properties = setupDialogProperties(DialogType.OPEN, properties);
return (sync) ? binding.showOpenDialogSync(settings) : binding.showOpenDialog(settings);
};
const messageBox = (sync, window, options) => {
checkAppInitialized();
if (window && window.constructor !== BrowserWindow) {
options = window;
window = null;
}
if (options == null) options = { type: 'none' };
const messageBoxTypes = ['none', 'info', 'warning', 'error', 'question'];
const messageBoxOptions = { noLink: 1 << 0 };
let {
buttons = [],
cancelId,
checkboxLabel = '',
checkboxChecked,
defaultId = -1,
detail = '',
icon = null,
noLink = false,
message = '',
title = '',
type = 'none'
} = options;
const messageBoxType = messageBoxTypes.indexOf(type);
if (messageBoxType === -1) throw new TypeError('Invalid message box type');
if (!Array.isArray(buttons)) throw new TypeError('Buttons must be an array');
if (options.normalizeAccessKeys) buttons = buttons.map(normalizeAccessKey);
if (typeof title !== 'string') throw new TypeError('Title must be a string');
if (typeof noLink !== 'boolean') throw new TypeError('noLink must be a boolean');
if (typeof message !== 'string') throw new TypeError('Message must be a string');
if (typeof detail !== 'string') throw new TypeError('Detail must be a string');
if (typeof checkboxLabel !== 'string') throw new TypeError('checkboxLabel must be a string');
checkboxChecked = !!checkboxChecked;
if (checkboxChecked && !checkboxLabel) {
throw new Error('checkboxChecked requires that checkboxLabel also be passed');
}
// Choose a default button to get selected when dialog is cancelled.
if (cancelId == null) {
// If the defaultId is set to 0, ensure the cancel button is a different index (1)
cancelId = (defaultId === 0 && buttons.length > 1) ? 1 : 0;
for (let i = 0; i < buttons.length; i++) {
const text = buttons[i].toLowerCase();
if (text === 'cancel' || text === 'no') {
cancelId = i;
break;
}
}
}
const settings = {
window,
messageBoxType,
buttons,
defaultId,
cancelId,
noLink,
title,
message,
detail,
checkboxLabel,
checkboxChecked,
icon
};
if (sync) {
return binding.showMessageBoxSync(settings);
} else {
return binding.showMessageBox(settings);
}
};
module.exports = {
showOpenDialog: function (window, options) {
return openDialog(false, window, options);
},
showOpenDialogSync: function (window, options) {
return openDialog(true, window, options);
},
showSaveDialog: function (window, options) {
return saveDialog(false, window, options);
},
showSaveDialogSync: function (window, options) {
return saveDialog(true, window, options);
},
showMessageBox: function (window, options) {
return messageBox(false, window, options);
},
showMessageBoxSync: function (window, options) {
return messageBox(true, window, options);
},
showErrorBox: function (...args) {
return binding.showErrorBox(...args);
},
showCertificateTrustDialog: function (window, options) {
if (window && window.constructor !== BrowserWindow) {
options = window;
window = null;
}
if (options == null || typeof options !== 'object') {
throw new TypeError('options must be an object');
}
const { certificate, message = '' } = options;
if (certificate == null || typeof certificate !== 'object') {
throw new TypeError('certificate must be an object');
}
if (typeof message !== 'string') throw new TypeError('message must be a string');
return binding.showCertificateTrustDialog(window, certificate, message);
}
};

View File

@@ -1,306 +0,0 @@
import { app, BrowserWindow } from 'electron';
import { OpenDialogOptions, OpenDialogReturnValue, MessageBoxOptions, SaveDialogOptions, SaveDialogReturnValue, MessageBoxReturnValue, CertificateTrustDialogOptions } from 'electron/main';
const dialogBinding = process._linkedBinding('electron_browser_dialog');
const DialogType = {
OPEN: 'OPEN' as 'OPEN',
SAVE: 'SAVE' as 'SAVE'
};
enum SaveFileDialogProperties {
createDirectory = 1 << 0,
showHiddenFiles = 1 << 1,
treatPackageAsDirectory = 1 << 2,
showOverwriteConfirmation = 1 << 3,
dontAddToRecent = 1 << 4
}
enum OpenFileDialogProperties {
openFile = 1 << 0,
openDirectory = 1 << 1,
multiSelections = 1 << 2,
createDirectory = 1 << 3, // macOS
showHiddenFiles = 1 << 4,
promptToCreate = 1 << 5, // Windows
noResolveAliases = 1 << 6, // macOS
treatPackageAsDirectory = 1 << 7, // macOS
dontAddToRecent = 1 << 8 // Windows
}
const normalizeAccessKey = (text: string) => {
if (typeof text !== 'string') return text;
// macOS does not have access keys so remove single ampersands
// and replace double ampersands with a single ampersand
if (process.platform === 'darwin') {
return text.replace(/&(&?)/g, '$1');
}
// Linux uses a single underscore as an access key prefix so escape
// existing single underscores with a second underscore, replace double
// ampersands with a single ampersand, and replace a single ampersand with
// a single underscore
if (process.platform === 'linux') {
return text.replace(/_/g, '__').replace(/&(.?)/g, (match, after) => {
if (after === '&') return after;
return `_${after}`;
});
}
return text;
};
const checkAppInitialized = function () {
if (!app.isReady()) {
throw new Error('dialog module can only be used after app is ready');
}
};
const setupOpenDialogProperties = (properties: (keyof typeof OpenFileDialogProperties)[]): number => {
let dialogProperties = 0;
for (const property of properties) {
if (Object.prototype.hasOwnProperty.call(OpenFileDialogProperties, property)) { dialogProperties |= OpenFileDialogProperties[property]; }
}
return dialogProperties;
};
const setupSaveDialogProperties = (properties: (keyof typeof SaveFileDialogProperties)[]): number => {
let dialogProperties = 0;
for (const property of properties) {
if (Object.prototype.hasOwnProperty.call(SaveFileDialogProperties, property)) { dialogProperties |= SaveFileDialogProperties[property]; }
}
return dialogProperties;
};
const setupDialogProperties = (type: keyof typeof DialogType, properties: string[]): number => {
if (type === DialogType.OPEN) {
return setupOpenDialogProperties(properties as (keyof typeof OpenFileDialogProperties)[]);
} else if (type === DialogType.SAVE) {
return setupSaveDialogProperties(properties as (keyof typeof SaveFileDialogProperties)[]);
} else {
return 0;
}
};
const saveDialog = (sync: boolean, window: BrowserWindow | null, options?: SaveDialogOptions) => {
checkAppInitialized();
if (options == null) options = { title: 'Save' };
const {
buttonLabel = '',
defaultPath = '',
filters = [],
properties = [],
title = '',
message = '',
securityScopedBookmarks = false,
nameFieldLabel = '',
showsTagField = true
} = options;
if (typeof title !== 'string') throw new TypeError('Title must be a string');
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string');
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string');
if (typeof message !== 'string') throw new TypeError('Message must be a string');
if (typeof nameFieldLabel !== 'string') throw new TypeError('Name field label must be a string');
const settings = {
buttonLabel,
defaultPath,
filters,
title,
message,
securityScopedBookmarks,
nameFieldLabel,
showsTagField,
window,
properties: setupDialogProperties(DialogType.SAVE, properties)
};
return sync ? dialogBinding.showSaveDialogSync(settings) : dialogBinding.showSaveDialog(settings);
};
const openDialog = (sync: boolean, window: BrowserWindow | null, options?: OpenDialogOptions) => {
checkAppInitialized();
if (options == null) {
options = {
title: 'Open',
properties: ['openFile']
};
}
const {
buttonLabel = '',
defaultPath = '',
filters = [],
properties = ['openFile'],
title = '',
message = '',
securityScopedBookmarks = false
} = options;
if (!Array.isArray(properties)) throw new TypeError('Properties must be an array');
if (typeof title !== 'string') throw new TypeError('Title must be a string');
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string');
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string');
if (typeof message !== 'string') throw new TypeError('Message must be a string');
const settings = {
title,
buttonLabel,
defaultPath,
filters,
message,
securityScopedBookmarks,
window,
properties: setupDialogProperties(DialogType.OPEN, properties)
};
return (sync) ? dialogBinding.showOpenDialogSync(settings) : dialogBinding.showOpenDialog(settings);
};
const messageBox = (sync: boolean, window: BrowserWindow | null, options?: MessageBoxOptions) => {
checkAppInitialized();
if (options == null) options = { type: 'none', message: '' };
const messageBoxTypes = ['none', 'info', 'warning', 'error', 'question'];
let {
buttons = [],
cancelId,
checkboxLabel = '',
checkboxChecked,
defaultId = -1,
detail = '',
icon = null,
noLink = false,
message = '',
title = '',
type = 'none'
} = options;
const messageBoxType = messageBoxTypes.indexOf(type);
if (messageBoxType === -1) throw new TypeError('Invalid message box type');
if (!Array.isArray(buttons)) throw new TypeError('Buttons must be an array');
if (options.normalizeAccessKeys) buttons = buttons.map(normalizeAccessKey);
if (typeof title !== 'string') throw new TypeError('Title must be a string');
if (typeof noLink !== 'boolean') throw new TypeError('noLink must be a boolean');
if (typeof message !== 'string') throw new TypeError('Message must be a string');
if (typeof detail !== 'string') throw new TypeError('Detail must be a string');
if (typeof checkboxLabel !== 'string') throw new TypeError('checkboxLabel must be a string');
checkboxChecked = !!checkboxChecked;
if (checkboxChecked && !checkboxLabel) {
throw new Error('checkboxChecked requires that checkboxLabel also be passed');
}
// Choose a default button to get selected when dialog is cancelled.
if (cancelId == null) {
// If the defaultId is set to 0, ensure the cancel button is a different index (1)
cancelId = (defaultId === 0 && buttons.length > 1) ? 1 : 0;
for (let i = 0; i < buttons.length; i++) {
const text = buttons[i].toLowerCase();
if (text === 'cancel' || text === 'no') {
cancelId = i;
break;
}
}
}
const settings = {
window,
messageBoxType,
buttons,
defaultId,
cancelId,
noLink,
title,
message,
detail,
checkboxLabel,
checkboxChecked,
icon
};
if (sync) {
return dialogBinding.showMessageBoxSync(settings);
} else {
return dialogBinding.showMessageBox(settings);
}
};
// eat dirt, eslint
/* eslint-disable import/export */
export function showOpenDialog(window: BrowserWindow, options: OpenDialogOptions): OpenDialogReturnValue;
export function showOpenDialog(options: OpenDialogOptions): OpenDialogReturnValue;
export function showOpenDialog (windowOrOptions: BrowserWindow | OpenDialogOptions, maybeOptions?: OpenDialogOptions): OpenDialogReturnValue {
const window = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? null : windowOrOptions);
const options = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? windowOrOptions : maybeOptions);
return openDialog(false, window, options);
}
export function showOpenDialogSync(window: BrowserWindow, options: OpenDialogOptions): OpenDialogReturnValue;
export function showOpenDialogSync(options: OpenDialogOptions): OpenDialogReturnValue;
export function showOpenDialogSync (windowOrOptions: BrowserWindow | OpenDialogOptions, maybeOptions?: OpenDialogOptions): OpenDialogReturnValue {
const window = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? null : windowOrOptions);
const options = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? windowOrOptions : maybeOptions);
return openDialog(true, window, options);
}
export function showSaveDialog(window: BrowserWindow, options: SaveDialogOptions): SaveDialogReturnValue;
export function showSaveDialog(options: SaveDialogOptions): SaveDialogReturnValue;
export function showSaveDialog (windowOrOptions: BrowserWindow | SaveDialogOptions, maybeOptions?: SaveDialogOptions): SaveDialogReturnValue {
const window = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? null : windowOrOptions);
const options = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? windowOrOptions : maybeOptions);
return saveDialog(false, window, options);
}
export function showSaveDialogSync(window: BrowserWindow, options: SaveDialogOptions): SaveDialogReturnValue;
export function showSaveDialogSync(options: SaveDialogOptions): SaveDialogReturnValue;
export function showSaveDialogSync (windowOrOptions: BrowserWindow | SaveDialogOptions, maybeOptions?: SaveDialogOptions): SaveDialogReturnValue {
const window = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? null : windowOrOptions);
const options = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? windowOrOptions : maybeOptions);
return saveDialog(true, window, options);
}
export function showMessageBox(window: BrowserWindow, options: MessageBoxOptions): MessageBoxReturnValue;
export function showMessageBox(options: MessageBoxOptions): MessageBoxReturnValue;
export function showMessageBox (windowOrOptions: BrowserWindow | MessageBoxOptions, maybeOptions?: MessageBoxOptions): MessageBoxReturnValue {
const window = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? null : windowOrOptions);
const options = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? windowOrOptions : maybeOptions);
return messageBox(false, window, options);
}
export function showMessageBoxSync(window: BrowserWindow, options: MessageBoxOptions): MessageBoxReturnValue;
export function showMessageBoxSync(options: MessageBoxOptions): MessageBoxReturnValue;
export function showMessageBoxSync (windowOrOptions: BrowserWindow | MessageBoxOptions, maybeOptions?: MessageBoxOptions): MessageBoxReturnValue {
const window = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? null : windowOrOptions);
const options = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? windowOrOptions : maybeOptions);
return messageBox(true, window, options);
}
export function showErrorBox (...args: any[]) {
return dialogBinding.showErrorBox(...args);
}
export function showCertificateTrustDialog (windowOrOptions: BrowserWindow | CertificateTrustDialogOptions, maybeOptions?: CertificateTrustDialogOptions) {
const window = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? null : windowOrOptions);
const options = (windowOrOptions && !(windowOrOptions instanceof BrowserWindow) ? windowOrOptions : maybeOptions);
if (options == null || typeof options !== 'object') {
throw new TypeError('options must be an object');
}
const { certificate, message = '' } = options;
if (certificate == null || typeof certificate !== 'object') {
throw new TypeError('certificate must be an object');
}
if (typeof message !== 'string') throw new TypeError('message must be a string');
return dialogBinding.showCertificateTrustDialog(window, certificate, message);
}

View File

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

View File

@@ -1,2 +0,0 @@
const { globalShortcut } = process._linkedBinding('electron_browser_global_shortcut');
export default globalShortcut;

View File

@@ -1,24 +1,22 @@
import { EventEmitter } from 'events';
'use strict';
let _inAppPurchase;
const { deprecate } = require('electron');
if (process.platform === 'darwin') {
const { inAppPurchase, InAppPurchase } = process._linkedBinding('electron_browser_in_app_purchase');
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);
_inAppPurchase = inAppPurchase;
module.exports = inAppPurchase;
} else {
_inAppPurchase = new EventEmitter();
Object.assign(_inAppPurchase, {
purchaseProduct: () => {
module.exports = {
purchaseProduct: (productID, quantity, callback) => {
throw new Error('The inAppPurchase module can only be used on macOS');
},
canMakePayments: () => false,
getReceiptURL: () => ''
});
};
}
export default _inAppPurchase;

View File

@@ -1,56 +1,44 @@
import { app, BrowserWindow, WebContents, MenuItemConstructorOptions } from 'electron';
'use strict';
const { app } = require('electron');
const isMac = process.platform === 'darwin';
const isWindows = process.platform === 'win32';
const isLinux = process.platform === 'linux';
type RoleId = 'about' | 'close' | 'copy' | 'cut' | 'delete' | 'forcereload' | 'front' | 'help' | 'hide' | 'hideothers' | 'minimize' |
'paste' | 'pasteandmatchstyle' | 'quit' | 'redo' | 'reload' | 'resetzoom' | 'selectall' | 'services' | 'recentdocuments' | 'clearrecentdocuments' | 'startspeaking' | 'stopspeaking' |
'toggledevtools' | 'togglefullscreen' | 'undo' | 'unhide' | 'window' | 'zoom' | 'zoomin' | 'zoomout' | 'appmenu' | 'filemenu' | 'editmenu' | 'viewmenu' | 'windowmenu'
interface Role {
label: string;
accelerator?: string;
windowMethod?: ((window: BrowserWindow) => void);
webContentsMethod?: ((webContents: WebContents) => void);
appMethod?: () => void;
registerAccelerator?: boolean;
nonNativeMacOSRole?: boolean;
submenu?: MenuItemConstructorOptions[];
}
export const roleList: Record<RoleId, Role> = {
const roles = {
about: {
get label () {
return isLinux ? 'About' : `About ${app.name}`;
},
...(isWindows && { appMethod: () => app.showAboutPanel() })
...(isWindows && { appMethod: 'showAboutPanel' })
},
close: {
label: isMac ? 'Close Window' : 'Close',
accelerator: 'CommandOrControl+W',
windowMethod: w => w.close()
windowMethod: 'close'
},
copy: {
label: 'Copy',
accelerator: 'CommandOrControl+C',
webContentsMethod: wc => wc.copy(),
webContentsMethod: 'copy',
registerAccelerator: false
},
cut: {
label: 'Cut',
accelerator: 'CommandOrControl+X',
webContentsMethod: wc => wc.cut(),
webContentsMethod: 'cut',
registerAccelerator: false
},
delete: {
label: 'Delete',
webContentsMethod: wc => wc.delete()
webContentsMethod: 'delete'
},
forcereload: {
label: 'Force Reload',
accelerator: 'Shift+CmdOrCtrl+R',
nonNativeMacOSRole: true,
windowMethod: (window: BrowserWindow) => {
windowMethod: (window) => {
window.webContents.reloadIgnoringCache();
}
},
@@ -73,18 +61,18 @@ export const roleList: Record<RoleId, Role> = {
minimize: {
label: 'Minimize',
accelerator: 'CommandOrControl+M',
windowMethod: w => w.minimize()
windowMethod: 'minimize'
},
paste: {
label: 'Paste',
accelerator: 'CommandOrControl+V',
webContentsMethod: wc => wc.paste(),
webContentsMethod: 'paste',
registerAccelerator: false
},
pasteandmatchstyle: {
label: 'Paste and Match Style',
accelerator: isMac ? 'Cmd+Option+Shift+V' : 'Shift+CommandOrControl+V',
webContentsMethod: wc => wc.pasteAndMatchStyle(),
webContentsMethod: 'pasteAndMatchStyle',
registerAccelerator: false
},
quit: {
@@ -96,31 +84,31 @@ export const roleList: Record<RoleId, Role> = {
}
},
accelerator: isWindows ? undefined : 'CommandOrControl+Q',
appMethod: () => app.quit()
appMethod: 'quit'
},
redo: {
label: 'Redo',
accelerator: isWindows ? 'Control+Y' : 'Shift+CommandOrControl+Z',
webContentsMethod: wc => wc.redo()
webContentsMethod: 'redo'
},
reload: {
label: 'Reload',
accelerator: 'CmdOrCtrl+R',
nonNativeMacOSRole: true,
windowMethod: w => w.reload()
windowMethod: 'reload'
},
resetzoom: {
label: 'Actual Size',
accelerator: 'CommandOrControl+0',
nonNativeMacOSRole: true,
webContentsMethod: (webContents: WebContents) => {
webContentsMethod: (webContents) => {
webContents.zoomLevel = 0;
}
},
selectall: {
label: 'Select All',
accelerator: 'CommandOrControl+A',
webContentsMethod: wc => wc.selectAll()
webContentsMethod: 'selectAll'
},
services: {
label: 'Services'
@@ -141,19 +129,19 @@ export const roleList: Record<RoleId, Role> = {
label: 'Toggle Developer Tools',
accelerator: isMac ? 'Alt+Command+I' : 'Ctrl+Shift+I',
nonNativeMacOSRole: true,
windowMethod: w => w.webContents.toggleDevTools()
windowMethod: 'toggleDevTools'
},
togglefullscreen: {
label: 'Toggle Full Screen',
accelerator: isMac ? 'Control+Command+F' : 'F11',
windowMethod: (window: BrowserWindow) => {
windowMethod: (window) => {
window.setFullScreen(!window.isFullScreen());
}
},
undo: {
label: 'Undo',
accelerator: 'CommandOrControl+Z',
webContentsMethod: wc => wc.undo()
webContentsMethod: 'undo'
},
unhide: {
label: 'Show All'
@@ -168,7 +156,7 @@ export const roleList: Record<RoleId, Role> = {
label: 'Zoom In',
accelerator: 'CommandOrControl+Plus',
nonNativeMacOSRole: true,
webContentsMethod: (webContents: WebContents) => {
webContentsMethod: (webContents) => {
webContents.zoomLevel += 0.5;
}
},
@@ -176,7 +164,7 @@ export const roleList: Record<RoleId, Role> = {
label: 'Zoom Out',
accelerator: 'CommandOrControl+-',
nonNativeMacOSRole: true,
webContentsMethod: (webContents: WebContents) => {
webContentsMethod: (webContents) => {
webContents.zoomLevel -= 0.5;
}
},
@@ -226,11 +214,11 @@ export const roleList: Record<RoleId, Role> = {
{ role: 'stopSpeaking' }
]
}
] as MenuItemConstructorOptions[] : [
] : [
{ role: 'delete' },
{ type: 'separator' },
{ role: 'selectAll' }
] as MenuItemConstructorOptions[])
])
]
},
// View submenu
@@ -257,38 +245,40 @@ export const roleList: Record<RoleId, Role> = {
...(isMac ? [
{ type: 'separator' },
{ role: 'front' }
] as MenuItemConstructorOptions[] : [
] : [
{ role: 'close' }
] as MenuItemConstructorOptions[])
])
]
}
};
const canExecuteRole = (role: keyof typeof roleList) => {
if (!Object.prototype.hasOwnProperty.call(roleList, role)) return false;
exports.roleList = roles;
const canExecuteRole = (role) => {
if (!Object.prototype.hasOwnProperty.call(roles, role)) return false;
if (!isMac) return true;
// macOS handles all roles natively except for a few
return roleList[role].nonNativeMacOSRole;
return roles[role].nonNativeMacOSRole;
};
export function getDefaultLabel (role: RoleId) {
return Object.prototype.hasOwnProperty.call(roleList, role) ? roleList[role].label : '';
}
exports.getDefaultLabel = (role) => {
return Object.prototype.hasOwnProperty.call(roles, role) ? roles[role].label : '';
};
export function getDefaultAccelerator (role: RoleId) {
if (Object.prototype.hasOwnProperty.call(roleList, role)) return roleList[role].accelerator;
}
exports.getDefaultAccelerator = (role) => {
if (Object.prototype.hasOwnProperty.call(roles, role)) return roles[role].accelerator;
};
export function shouldRegisterAccelerator (role: RoleId) {
const hasRoleRegister = Object.prototype.hasOwnProperty.call(roleList, role) && roleList[role].registerAccelerator !== undefined;
return hasRoleRegister ? roleList[role].registerAccelerator : true;
}
exports.shouldRegisterAccelerator = (role) => {
const hasRoleRegister = Object.prototype.hasOwnProperty.call(roles, role) && roles[role].registerAccelerator !== undefined;
return hasRoleRegister ? roles[role].registerAccelerator : true;
};
export function getDefaultSubmenu (role: RoleId) {
if (!Object.prototype.hasOwnProperty.call(roleList, role)) return;
exports.getDefaultSubmenu = (role) => {
if (!Object.prototype.hasOwnProperty.call(roles, role)) return;
let { submenu } = roleList[role];
let { submenu } = roles[role];
// remove null items from within the submenu
if (Array.isArray(submenu)) {
@@ -296,27 +286,35 @@ export function getDefaultSubmenu (role: RoleId) {
}
return submenu;
}
};
export function execute (role: RoleId, focusedWindow: BrowserWindow, focusedWebContents: WebContents) {
exports.execute = (role, focusedWindow, focusedWebContents) => {
if (!canExecuteRole(role)) return false;
const { appMethod, webContentsMethod, windowMethod } = roleList[role];
const { appMethod, webContentsMethod, windowMethod } = roles[role];
if (appMethod) {
appMethod();
app[appMethod]();
return true;
}
if (windowMethod && focusedWindow != null) {
windowMethod(focusedWindow);
if (typeof windowMethod === 'function') {
windowMethod(focusedWindow);
} else {
focusedWindow[windowMethod]();
}
return true;
}
if (webContentsMethod && focusedWebContents != null) {
webContentsMethod(focusedWebContents);
if (typeof webContentsMethod === 'function') {
webContentsMethod(focusedWebContents);
} else {
focusedWebContents[webContentsMethod]();
}
return true;
}
return false;
}
};

View File

@@ -1,9 +1,12 @@
import * as roles from './menu-item-roles';
import { Menu, Event, BrowserWindow, WebContents } from 'electron';
'use strict';
const roles = require('@electron/internal/browser/api/menu-item-roles');
let nextCommandId = 0;
const MenuItem = function (this: any, options: any) {
const MenuItem = function (options) {
const { Menu } = require('electron');
// Preserve extra fields specified by user
for (const key in options) {
if (!(key in this)) this[key] = options[key];
@@ -44,7 +47,7 @@ const MenuItem = function (this: any, options: any) {
this.overrideReadOnlyProperty('commandId', ++nextCommandId);
const click = options.click;
this.click = (event: Event, focusedWindow: BrowserWindow, focusedWebContents: WebContents) => {
this.click = (event, focusedWindow, focusedWebContents) => {
// Manually flip the checked flags when clicked.
if (this.type === 'checkbox' || this.type === 'radio') {
this.checked = !this.checked;
@@ -66,13 +69,13 @@ MenuItem.prototype.getDefaultRoleAccelerator = function () {
return roles.getDefaultAccelerator(this.role);
};
MenuItem.prototype.overrideProperty = function (name: string, defaultValue: any = null) {
MenuItem.prototype.overrideProperty = function (name, defaultValue = null) {
if (this[name] == null) {
this[name] = defaultValue;
}
};
MenuItem.prototype.overrideReadOnlyProperty = function (name: string, defaultValue: any) {
MenuItem.prototype.overrideReadOnlyProperty = function (name, defaultValue) {
this.overrideProperty(name, defaultValue);
Object.defineProperty(this, name, {
enumerable: true,

View File

@@ -1,4 +1,6 @@
function splitArray<T> (arr: T[], predicate: (x: T) => boolean) {
'use strict';
function splitArray (arr, predicate) {
const result = arr.reduce((multi, item) => {
const current = multi[multi.length - 1];
if (predicate(item)) {
@@ -7,7 +9,7 @@ function splitArray<T> (arr: T[], predicate: (x: T) => boolean) {
current.push(item);
}
return multi;
}, [[]] as T[][]);
}, [[]]);
if (result[result.length - 1].length === 0) {
return result.slice(0, result.length - 1);
@@ -15,7 +17,7 @@ function splitArray<T> (arr: T[], predicate: (x: T) => boolean) {
return result;
}
function joinArrays (arrays: any[][], joinIDs: any[]) {
function joinArrays (arrays, joinIDs) {
return arrays.reduce((joined, arr, i) => {
if (i > 0 && arr.length) {
if (joinIDs.length > 0) {
@@ -29,14 +31,14 @@ function joinArrays (arrays: any[][], joinIDs: any[]) {
}, []);
}
function pushOntoMultiMap<K, V> (map: Map<K, V[]>, key: K, value: V) {
function pushOntoMultiMap (map, key, value) {
if (!map.has(key)) {
map.set(key, []);
}
map.get(key)!.push(value);
map.get(key).push(value);
}
function indexOfGroupContainingID<T> (groups: {id?: T}[][], id: T, ignoreGroup: {id?: T}[]) {
function indexOfGroupContainingID (groups, id, ignoreGroup) {
return groups.findIndex(
candidateGroup =>
candidateGroup !== ignoreGroup &&
@@ -48,11 +50,11 @@ function indexOfGroupContainingID<T> (groups: {id?: T}[][], id: T, ignoreGroup:
// Sort nodes topologically using a depth-first approach. Encountered cycles
// are broken.
function sortTopologically<T> (originalOrder: T[], edgesById: Map<T, T[]>) {
const sorted = [] as T[];
const marked = new Set<T>();
function sortTopologically (originalOrder, edgesById) {
const sorted = [];
const marked = new Set();
const visit = (mark: T) => {
const visit = (mark) => {
if (marked.has(mark)) return;
marked.add(mark);
const edges = edgesById.get(mark);
@@ -66,7 +68,7 @@ function sortTopologically<T> (originalOrder: T[], edgesById: Map<T, T[]>) {
return sorted;
}
function attemptToMergeAGroup<T> (groups: {before?: T[], after?: T[], id?: T}[][]) {
function attemptToMergeAGroup (groups) {
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
for (const item of group) {
@@ -85,7 +87,7 @@ function attemptToMergeAGroup<T> (groups: {before?: T[], after?: T[], id?: T}[][
return false;
}
function mergeGroups<T> (groups: {before?: T[], after?: T[], id?: T}[][]) {
function mergeGroups (groups) {
let merged = true;
while (merged) {
merged = attemptToMergeAGroup(groups);
@@ -93,7 +95,7 @@ function mergeGroups<T> (groups: {before?: T[], after?: T[], id?: T}[][]) {
return groups;
}
function sortItemsInGroup<T> (group: {before?: T[], after?: T[], id?: T}[]) {
function sortItemsInGroup (group) {
const originalOrder = group.map((node, i) => i);
const edges = new Map();
const idToIndex = new Map(group.map((item, i) => [item.id, i]));
@@ -121,7 +123,7 @@ function sortItemsInGroup<T> (group: {before?: T[], after?: T[], id?: T}[]) {
return sortedNodes.map(i => group[i]);
}
function findEdgesInGroup<T> (groups: {beforeGroupContaining?: T[], afterGroupContaining?: T[], id?: T}[][], i: number, edges: Map<any, any>) {
function findEdgesInGroup (groups, i, edges) {
const group = groups[i];
for (const item of group) {
if (item.beforeGroupContaining) {
@@ -145,7 +147,7 @@ function findEdgesInGroup<T> (groups: {beforeGroupContaining?: T[], afterGroupCo
}
}
function sortGroups<T> (groups: {id?: T}[][]) {
function sortGroups (groups) {
const originalOrder = groups.map((item, i) => i);
const edges = new Map();
@@ -157,8 +159,8 @@ function sortGroups<T> (groups: {id?: T}[][]) {
return sortedGroupIndexes.map(i => groups[i]);
}
export function sortMenuItems (menuItems: {type?: string, id?: string}[]) {
const isSeparator = (item: {type?: string}) => item.type === 'separator';
function sortMenuItems (menuItems) {
const isSeparator = (item) => item.type === 'separator';
const separators = menuItems.filter(i => i.type === 'separator');
// Split the items into their implicit groups based upon separators.
@@ -170,3 +172,5 @@ export function sortMenuItems (menuItems: {type?: string, id?: string}[]) {
const joined = joinArrays(sortedGroups, separators);
return joined;
}
module.exports = { sortMenuItems };

View File

@@ -1,11 +1,13 @@
import { BaseWindow, MenuItem, webContents, Menu as MenuType, BrowserWindow, MenuItemConstructorOptions } from 'electron';
import { sortMenuItems } from './menu-utils';
'use strict';
const v8Util = process._linkedBinding('electron_common_v8_util');
const bindings = process._linkedBinding('electron_browser_menu');
const { TopLevelWindow, MenuItem, webContents } = require('electron');
const { sortMenuItems } = require('@electron/internal/browser/api/menu-utils');
const EventEmitter = require('events').EventEmitter;
const v8Util = process.electronBinding('v8_util');
const bindings = process.electronBinding('menu');
const { Menu } = bindings as { Menu: typeof MenuType };
let applicationMenu: MenuType | null = null;
const { Menu } = bindings;
let applicationMenu = null;
let groupIdIndex = 0;
/* Instance Methods */
@@ -17,17 +19,17 @@ Menu.prototype._init = function () {
};
Menu.prototype._isCommandIdChecked = function (id) {
return this.commandsMap[id] ? this.commandsMap[id].checked : false;
return this.commandsMap[id] ? this.commandsMap[id].checked : undefined;
};
Menu.prototype._isCommandIdEnabled = function (id) {
return this.commandsMap[id] ? this.commandsMap[id].enabled : false;
return this.commandsMap[id] ? this.commandsMap[id].enabled : undefined;
};
Menu.prototype._shouldCommandIdWorkWhenHidden = function (id) {
return this.commandsMap[id] ? !!this.commandsMap[id].acceleratorWorksWhenHidden : false;
return this.commandsMap[id] ? this.commandsMap[id].acceleratorWorksWhenHidden : undefined;
};
Menu.prototype._isCommandIdVisible = function (id) {
return this.commandsMap[id] ? this.commandsMap[id].visible : false;
return this.commandsMap[id] ? this.commandsMap[id].visible : undefined;
};
Menu.prototype._getAcceleratorForCommandId = function (id, useDefaultAccelerator) {
@@ -38,14 +40,13 @@ Menu.prototype._getAcceleratorForCommandId = function (id, useDefaultAccelerator
};
Menu.prototype._shouldRegisterAcceleratorForCommandId = function (id) {
return this.commandsMap[id] ? this.commandsMap[id].registerAccelerator : false;
return this.commandsMap[id] ? this.commandsMap[id].registerAccelerator : undefined;
};
Menu.prototype._executeCommand = function (event, id) {
const command = this.commandsMap[id];
if (!command) return;
const focusedWindow = BaseWindow.getFocusedWindow();
command.click(event, focusedWindow instanceof BrowserWindow ? focusedWindow : undefined, webContents.getFocusedWebContents());
command.click(event, TopLevelWindow.getFocusedWindow(), webContents.getFocusedWebContents());
};
Menu.prototype._menuWillShow = function () {
@@ -71,23 +72,23 @@ Menu.prototype.popup = function (options = {}) {
if (typeof positioningItem !== 'number') positioningItem = -1;
// find which window to use
const wins = BaseWindow.getAllWindows();
if (!wins || wins.indexOf(window as any) === -1) {
window = BaseWindow.getFocusedWindow() as any;
const wins = TopLevelWindow.getAllWindows();
if (!wins || wins.indexOf(window) === -1) {
window = TopLevelWindow.getFocusedWindow();
if (!window && wins && wins.length > 0) {
window = wins[0] as any;
window = wins[0];
}
if (!window) {
throw new Error('Cannot open Menu without a BaseWindow present');
throw new Error('Cannot open Menu without a TopLevelWindow present');
}
}
this.popupAt(window as unknown as BaseWindow, x, y, positioningItem, callback);
this.popupAt(window, x, y, positioningItem, callback);
return { browserWindow: window, x, y, position: positioningItem };
};
Menu.prototype.closePopup = function (window) {
if (window instanceof BaseWindow) {
if (window instanceof TopLevelWindow) {
this.closePopupAt(window.id);
} else {
// Passing -1 (invalid) would make closePopupAt close the all menu runners
@@ -101,9 +102,8 @@ Menu.prototype.getMenuItemById = function (id) {
let found = items.find(item => item.id === id) || null;
for (let i = 0; !found && i < items.length; i++) {
const { submenu } = items[i];
if (submenu) {
found = submenu.getMenuItemById(id);
if (items[i].submenu) {
found = items[i].submenu.getMenuItemById(id);
}
}
return found;
@@ -155,7 +155,7 @@ Menu.getApplicationMenu = () => applicationMenu;
Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder;
// set application menu with a preexisting menu
Menu.setApplicationMenu = function (menu: MenuType) {
Menu.setApplicationMenu = function (menu) {
if (menu && menu.constructor !== Menu) {
throw new TypeError('Invalid menu');
}
@@ -168,7 +168,7 @@ Menu.setApplicationMenu = function (menu: MenuType) {
menu._callMenuWillShow();
bindings.setApplicationMenu(menu);
} else {
const windows = BaseWindow.getAllWindows();
const windows = TopLevelWindow.getAllWindows();
return windows.map(w => w.setMenu(menu));
}
};
@@ -200,7 +200,7 @@ Menu.buildFromTemplate = function (template) {
/* Helper Functions */
// validate the template against having the wrong attribute
function areValidTemplateItems (template: (MenuItemConstructorOptions | MenuItem)[]) {
function areValidTemplateItems (template) {
return template.every(item =>
item != null &&
typeof item === 'object' &&
@@ -209,7 +209,7 @@ function areValidTemplateItems (template: (MenuItemConstructorOptions | MenuItem
item.type === 'separator'));
}
function sortTemplate (template: (MenuItemConstructorOptions | MenuItem)[]) {
function sortTemplate (template) {
const sorted = sortMenuItems(template);
for (const item of sorted) {
if (Array.isArray(item.submenu)) {
@@ -220,15 +220,15 @@ function sortTemplate (template: (MenuItemConstructorOptions | MenuItem)[]) {
}
// Search between separators to find a radio menu item and return its group id
function generateGroupId (items: (MenuItemConstructorOptions | MenuItem)[], pos: number) {
function generateGroupId (items, pos) {
if (pos > 0) {
for (let idx = pos - 1; idx >= 0; idx--) {
if (items[idx].type === 'radio') return (items[idx] as any).groupId;
if (items[idx].type === 'radio') return items[idx].groupId;
if (items[idx].type === 'separator') break;
}
} else if (pos < items.length) {
for (let idx = pos; idx <= items.length - 1; idx++) {
if (items[idx].type === 'radio') return (items[idx] as any).groupId;
if (items[idx].type === 'radio') return items[idx].groupId;
if (items[idx].type === 'separator') break;
}
}
@@ -236,7 +236,7 @@ function generateGroupId (items: (MenuItemConstructorOptions | MenuItem)[], pos:
return groupIdIndex;
}
function removeExtraSeparators (items: (MenuItemConstructorOptions | MenuItem)[]) {
function removeExtraSeparators (items) {
// fold adjacent separators together
let ret = items.filter((e, idx, arr) => {
if (e.visible === false) return true;
@@ -252,7 +252,7 @@ function removeExtraSeparators (items: (MenuItemConstructorOptions | MenuItem)[]
return ret;
}
function insertItemByType (this: MenuType, item: MenuItem, pos: number) {
function insertItemByType (item, pos) {
const types = {
normal: () => this.insertItem(pos, item.commandId, item.label),
checkbox: () => this.insertCheckItem(pos, item.commandId, item.label),

View File

@@ -1,5 +1,5 @@
import { MessagePortMain } from '@electron/internal/browser/message-port-main';
const { createPair } = process._linkedBinding('electron_browser_message_port');
const { createPair } = process.electronBinding('message_port');
export default class MessageChannelMain {
port1: MessagePortMain;

View File

@@ -4,7 +4,6 @@
export const browserModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'app', loader: () => require('./app') },
{ name: 'autoUpdater', loader: () => require('./auto-updater') },
{ name: 'BaseWindow', loader: () => require('./base-window') },
{ name: 'BrowserView', loader: () => require('./browser-view') },
{ name: 'BrowserWindow', loader: () => require('./browser-window') },
{ name: 'contentTracing', loader: () => require('./content-tracing') },
@@ -26,6 +25,7 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'screen', loader: () => require('./screen') },
{ name: 'session', loader: () => require('./session') },
{ name: 'systemPreferences', loader: () => require('./system-preferences') },
{ name: 'TopLevelWindow', loader: () => require('./top-level-window') },
{ name: 'TouchBar', loader: () => require('./touch-bar') },
{ name: 'Tray', loader: () => require('./tray') },
{ name: 'View', loader: () => require('./view') },

View File

@@ -7,7 +7,6 @@
export const browserModuleNames = [
'app',
'autoUpdater',
'BaseWindow',
'BrowserView',
'BrowserWindow',
'contentTracing',
@@ -29,6 +28,7 @@ export const browserModuleNames = [
'screen',
'session',
'systemPreferences',
'TopLevelWindow',
'TouchBar',
'Tray',
'View',

View File

@@ -1,6 +1,6 @@
import { EventEmitter } from 'events';
const { NativeTheme, nativeTheme } = process._linkedBinding('electron_common_native_theme');
const { NativeTheme, nativeTheme } = process.electronBinding('native_theme');
Object.setPrototypeOf(NativeTheme.prototype, EventEmitter.prototype);
EventEmitter.call(nativeTheme as any);

View File

@@ -0,0 +1,32 @@
'use strict';
// TODO(deepak1556): Deprecate and remove standalone netLog module,
// it is now a property of session module.
const { app, session } = require('electron');
// Fallback to default session.
Object.setPrototypeOf(module.exports, new Proxy({}, {
get (target, property) {
if (!app.isReady()) return;
const netLog = session.defaultSession.netLog;
if (!Object.prototype.hasOwnProperty.call(Object.getPrototypeOf(netLog), property)) return;
// check for properties on the prototype chain that aren't functions
if (typeof netLog[property] !== 'function') return netLog[property];
// Returning a native function directly would throw error.
return (...args) => netLog[property](...args);
},
ownKeys () {
if (!app.isReady()) return [];
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession.netLog));
},
getOwnPropertyDescriptor (target) {
return { configurable: true, enumerable: true };
}
}));

View File

@@ -1,22 +0,0 @@
// TODO(deepak1556): Deprecate and remove standalone netLog module,
// it is now a property of session module.
import { app, session } from 'electron';
const startLogging: typeof session.defaultSession.netLog.startLogging = async (path, options) => {
if (!app.isReady()) return;
return session.defaultSession.netLog.startLogging(path, options);
};
const stopLogging: typeof session.defaultSession.netLog.stopLogging = async () => {
if (!app.isReady()) return;
return session.defaultSession.netLog.stopLogging();
};
export default {
startLogging,
stopLogging,
get currentlyLogging (): boolean {
if (!app.isReady()) return false;
return session.defaultSession.netLog.currentlyLogging;
}
};

View File

@@ -2,13 +2,7 @@ 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._linkedBinding('electron_browser_net');
const { net, Net, isValidHeaderName, isValidHeaderValue, createURLLoader } = process.electronBinding('net');
const kSupportedProtocols = new Set(['http:', 'https:']);
@@ -300,10 +294,6 @@ class ClientRequest extends Writable implements Electron.ClientRequest {
this._redirectPolicy = redirectPolicy;
}
get chunkedEncoding () {
return this._chunkedEncoding || false;
}
set chunkedEncoding (value: boolean) {
if (this._started) {
throw new Error('chunkedEncoding can only be set before the request is started');

View File

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

View File

@@ -1,8 +0,0 @@
const {
Notification: ElectronNotification,
isSupported
} = process._linkedBinding('electron_common_notification');
ElectronNotification.isSupported = isSupported;
export default ElectronNotification;

View File

@@ -1,11 +1,7 @@
import { EventEmitter } from 'events';
import { app } from 'electron';
const {
createPowerMonitor,
getSystemIdleState,
getSystemIdleTime
} = process._linkedBinding('electron_browser_power_monitor');
const { createPowerMonitor, getSystemIdleState, getSystemIdleTime } = process.electronBinding('power_monitor');
class PowerMonitor extends EventEmitter {
constructor () {

View File

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

View File

@@ -1,2 +0,0 @@
const { powerSaveBlocker } = process._linkedBinding('electron_browser_power_save_blocker');
export default powerSaveBlocker;

View File

@@ -1,7 +1,7 @@
import { app, session } from 'electron';
// Global protocol APIs.
const protocol = process._linkedBinding('electron_browser_protocol');
const protocol = process.electronBinding('protocol');
// Fallback protocol APIs of default session.
Object.setPrototypeOf(protocol, new Proxy({}, {

View File

@@ -2,7 +2,7 @@
import { createLazyInstance } from '../utils';
const { EventEmitter } = require('events');
const { Screen, createScreen } = process._linkedBinding('electron_common_screen');
const { Screen, createScreen } = process.electronBinding('screen');
// Screen is an EventEmitter.
Object.setPrototypeOf(Screen.prototype, EventEmitter.prototype);

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
import { EventEmitter } from 'events';
import { deprecate } from 'electron';
const { systemPreferences, SystemPreferences } = process._linkedBinding('electron_browser_system_preferences');
const { systemPreferences, SystemPreferences } = process.electronBinding('system_preferences');
// SystemPreferences is an EventEmitter.
Object.setPrototypeOf(SystemPreferences.prototype, EventEmitter.prototype);

View File

@@ -1,12 +1,14 @@
import { EventEmitter } from 'events';
import type { BaseWindow as TLWT } from 'electron';
const { BaseWindow } = process._linkedBinding('electron_browser_base_window') as { BaseWindow: typeof TLWT };
'use strict';
Object.setPrototypeOf(BaseWindow.prototype, EventEmitter.prototype);
const electron = require('electron');
const { EventEmitter } = require('events');
const { TopLevelWindow } = process.electronBinding('top_level_window');
(BaseWindow.prototype as any)._init = function () {
Object.setPrototypeOf(TopLevelWindow.prototype, EventEmitter.prototype);
TopLevelWindow.prototype._init = function () {
// Avoid recursive require.
const { app } = require('electron');
const { app } = electron;
// Simulate the application menu on platforms other than macOS.
if (process.platform !== 'darwin') {
@@ -17,88 +19,88 @@ Object.setPrototypeOf(BaseWindow.prototype, EventEmitter.prototype);
// Properties
Object.defineProperty(BaseWindow.prototype, 'autoHideMenuBar', {
Object.defineProperty(TopLevelWindow.prototype, 'autoHideMenuBar', {
get: function () { return this.isMenuBarAutoHide(); },
set: function (autoHide) { this.setAutoHideMenuBar(autoHide); }
});
Object.defineProperty(BaseWindow.prototype, 'visibleOnAllWorkspaces', {
Object.defineProperty(TopLevelWindow.prototype, 'visibleOnAllWorkspaces', {
get: function () { return this.isVisibleOnAllWorkspaces(); },
set: function (visible) { this.setVisibleOnAllWorkspaces(visible); }
});
Object.defineProperty(BaseWindow.prototype, 'fullScreen', {
Object.defineProperty(TopLevelWindow.prototype, 'fullScreen', {
get: function () { return this.isFullScreen(); },
set: function (full) { this.setFullScreen(full); }
});
Object.defineProperty(BaseWindow.prototype, 'simpleFullScreen', {
Object.defineProperty(TopLevelWindow.prototype, 'simpleFullScreen', {
get: function () { return this.isSimpleFullScreen(); },
set: function (simple) { this.setSimpleFullScreen(simple); }
});
Object.defineProperty(BaseWindow.prototype, 'kiosk', {
Object.defineProperty(TopLevelWindow.prototype, 'kiosk', {
get: function () { return this.isKiosk(); },
set: function (kiosk) { this.setKiosk(kiosk); }
});
Object.defineProperty(BaseWindow.prototype, 'documentEdited', {
Object.defineProperty(TopLevelWindow.prototype, 'documentEdited', {
get: function () { return this.isFullscreen(); },
set: function (edited) { this.setDocumentEdited(edited); }
});
Object.defineProperty(BaseWindow.prototype, 'shadow', {
Object.defineProperty(TopLevelWindow.prototype, 'shadow', {
get: function () { return this.hasShadow(); },
set: function (shadow) { this.setHasShadow(shadow); }
});
Object.defineProperty(BaseWindow.prototype, 'representedFilename', {
Object.defineProperty(TopLevelWindow.prototype, 'representedFilename', {
get: function () { return this.getRepresentedFilename(); },
set: function (filename) { this.setRepresentedFilename(filename); }
});
Object.defineProperty(BaseWindow.prototype, 'minimizable', {
Object.defineProperty(TopLevelWindow.prototype, 'minimizable', {
get: function () { return this.isMinimizable(); },
set: function (min) { this.setMinimizable(min); }
});
Object.defineProperty(BaseWindow.prototype, 'title', {
Object.defineProperty(TopLevelWindow.prototype, 'title', {
get: function () { return this.getTitle(); },
set: function (title) { this.setTitle(title); }
});
Object.defineProperty(BaseWindow.prototype, 'maximizable', {
Object.defineProperty(TopLevelWindow.prototype, 'maximizable', {
get: function () { return this.isMaximizable(); },
set: function (max) { this.setMaximizable(max); }
});
Object.defineProperty(BaseWindow.prototype, 'resizable', {
Object.defineProperty(TopLevelWindow.prototype, 'resizable', {
get: function () { return this.isResizable(); },
set: function (res) { this.setResizable(res); }
});
Object.defineProperty(BaseWindow.prototype, 'menuBarVisible', {
Object.defineProperty(TopLevelWindow.prototype, 'menuBarVisible', {
get: function () { return this.isMenuBarVisible(); },
set: function (visible) { this.setMenuBarVisibility(visible); }
});
Object.defineProperty(BaseWindow.prototype, 'fullScreenable', {
Object.defineProperty(TopLevelWindow.prototype, 'fullScreenable', {
get: function () { return this.isFullScreenable(); },
set: function (full) { this.setFullScreenable(full); }
});
Object.defineProperty(BaseWindow.prototype, 'closable', {
Object.defineProperty(TopLevelWindow.prototype, 'closable', {
get: function () { return this.isClosable(); },
set: function (close) { this.setClosable(close); }
});
Object.defineProperty(BaseWindow.prototype, 'movable', {
Object.defineProperty(TopLevelWindow.prototype, 'movable', {
get: function () { return this.isMovable(); },
set: function (move) { this.setMovable(move); }
});
BaseWindow.getFocusedWindow = () => {
return BaseWindow.getAllWindows().find((win) => win.isFocused());
TopLevelWindow.getFocusedWindow = () => {
return TopLevelWindow.getAllWindows().find((win) => win.isFocused());
};
module.exports = BaseWindow;
module.exports = TopLevelWindow;

5
lib/browser/api/tray.js Normal file
View File

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

View File

@@ -1,3 +0,0 @@
const { Tray } = process._linkedBinding('electron_browser_tray');
export default Tray;

5
lib/browser/api/view.js Normal file
View File

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

View File

@@ -1,3 +0,0 @@
const { View } = process._linkedBinding('electron_browser_view');
export default View;

View File

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

View File

@@ -1,7 +0,0 @@
import { View } from 'electron';
const { ImageView } = process._linkedBinding('electron_browser_image_view');
Object.setPrototypeOf(ImageView.prototype, View.prototype);
export default ImageView;

View File

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

View File

@@ -1,7 +0,0 @@
import { View } from 'electron';
const { WebContentsView } = process._linkedBinding('electron_browser_web_contents_view');
Object.setPrototypeOf(WebContentsView.prototype, View.prototype);
export default WebContentsView;

View File

@@ -1,15 +1,17 @@
import { app, ipcMain, session, deprecate } from 'electron';
import type { MenuItem, MenuItemConstructorOptions, WebContentsInternal } from 'electron';
'use strict';
import * as url from 'url';
import * as path from 'path';
import { internalWindowOpen } from '../guest-window-manager';
import { NavigationController } from '../navigation-controller';
import { ipcMainInternal } from '../ipc-main-internal';
import * as ipcMainUtils from '../ipc-main-internal-utils';
import { parseFeatures } from '../../common/parse-features-string';
import { MessagePortMain } from '../message-port-main';
import { EventEmitter } from 'events';
const { EventEmitter } = require('events');
const electron = require('electron');
const path = require('path');
const url = require('url');
const { app, ipcMain, session } = electron;
const { internalWindowOpen } = require('@electron/internal/browser/guest-window-manager');
const NavigationController = require('@electron/internal/browser/navigation-controller');
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal');
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils');
const { parseFeatures } = require('@electron/internal/common/parse-features-string');
const { MessagePortMain } = require('@electron/internal/browser/message-port-main');
// session is not used here, the purpose is to make sure session is initalized
// before the webContents module.
@@ -21,18 +23,8 @@ const getNextId = function () {
return ++nextId;
};
/* eslint-disable camelcase */
type MediaSize = {
name: string,
custom_display_name: string,
height_microns: number,
width_microns: number,
is_default?: 'true',
}
/* eslint-enable camelcase */
// Stock page sizes
const PDFPageSizes: Record<string, MediaSize> = {
const PDFPageSizes = {
A5: {
custom_display_name: 'A5',
height_microns: 210000,
@@ -75,8 +67,8 @@ const PDFPageSizes: Record<string, MediaSize> = {
// Default printing setting
const defaultPrintingSetting = {
// Customizable.
pageRange: [] as {from: number, to: number}[],
mediaSize: {} as MediaSize,
pageRange: [],
mediaSize: {},
landscape: false,
headerFooterEnabled: false,
marginsType: 0,
@@ -101,18 +93,18 @@ const defaultPrintingSetting = {
copies: 1,
// 2 = color - see ColorModel in //printing/print_job_constants.h
color: 2,
collate: true,
printerType: 2,
title: undefined as string | undefined,
url: undefined as string | undefined
collate: true
};
// JavaScript implementations of WebContents.
const binding = process._linkedBinding('electron_browser_web_contents');
const { WebContents } = binding as { WebContents: { prototype: WebContentsInternal } };
const binding = process.electronBinding('web_contents');
const { WebContents } = binding;
Object.setPrototypeOf(WebContents.prototype, EventEmitter.prototype);
Object.setPrototypeOf(NavigationController.prototype, EventEmitter.prototype);
Object.setPrototypeOf(WebContents.prototype, NavigationController.prototype);
// WebContents::send(channel, args..)
// WebContents::sendToAll(channel, args..)
WebContents.prototype.send = function (channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument');
@@ -131,6 +123,17 @@ WebContents.prototype.postMessage = function (...args) {
this._postMessage(...args);
};
WebContents.prototype.sendToAll = function (channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument');
}
const internal = false;
const sendToAll = true;
return this._send(internal, sendToAll, channel, args);
};
WebContents.prototype._sendInternal = function (channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument');
@@ -182,15 +185,15 @@ const webFrameMethods = [
'insertText',
'removeInsertedCSS',
'setVisualZoomLevelLimits'
] as ('insertCSS' | 'insertText' | 'removeInsertedCSS' | 'setVisualZoomLevelLimits')[];
];
for (const method of webFrameMethods) {
WebContents.prototype[method] = function (...args: any[]): Promise<any> {
WebContents.prototype[method] = function (...args) {
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, ...args);
};
}
const waitTillCanExecuteJavaScript = async (webContents: WebContentsInternal) => {
const waitTillCanExecuteJavaScript = async (webContents) => {
if (webContents.getURL() && !webContents.isLoadingMainFrame()) return;
return new Promise((resolve) => {
@@ -204,15 +207,17 @@ const waitTillCanExecuteJavaScript = async (webContents: WebContentsInternal) =>
// WebContents has been loaded.
WebContents.prototype.executeJavaScript = async function (code, hasUserGesture) {
await waitTillCanExecuteJavaScript(this);
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScript', String(code), !!hasUserGesture);
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScript', code, hasUserGesture);
};
WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (worldId, code, hasUserGesture) {
WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (code, hasUserGesture) {
await waitTillCanExecuteJavaScript(this);
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScriptInIsolatedWorld', worldId, code, !!hasUserGesture);
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScriptInIsolatedWorld', code, hasUserGesture);
};
// Translate the options of printToPDF.
WebContents.prototype.printToPDF = function (options) {
let pendingPromise;
WebContents.prototype.printToPDF = async function (options) {
const printSettings = {
...defaultPrintingSetting,
requestID: getNextId()
@@ -323,7 +328,7 @@ WebContents.prototype.printToPDF = function (options) {
height_microns: Math.ceil(pageSize.height),
width_microns: Math.ceil(pageSize.width)
};
} else if (Object.prototype.hasOwnProperty.call(PDFPageSizes, pageSize)) {
} else if (PDFPageSizes[pageSize]) {
printSettings.mediaSize = PDFPageSizes[pageSize];
} else {
const error = new Error(`Unsupported pageSize: ${pageSize}`);
@@ -338,7 +343,12 @@ WebContents.prototype.printToPDF = function (options) {
// PrinterType enum from //printing/print_job_constants.h
printSettings.printerType = 2;
if (this._printToPDF) {
return this._printToPDF(printSettings);
if (pendingPromise) {
pendingPromise = pendingPromise.then(() => this._printToPDF(printSettings));
} else {
pendingPromise = this._printToPDF(printSettings);
}
return pendingPromise;
} else {
const error = new Error('Printing feature is disabled');
return Promise.reject(error);
@@ -357,14 +367,14 @@ WebContents.prototype.print = function (options = {}, callback) {
throw new Error('height and width properties are required for pageSize');
}
// Dimensions in Microns - 1 meter = 10^6 microns
(options as any).mediaSize = {
options.mediaSize = {
name: 'CUSTOM',
custom_display_name: 'Custom',
height_microns: Math.ceil(pageSize.height),
width_microns: Math.ceil(pageSize.width)
};
} else if (PDFPageSizes[pageSize]) {
(options as any).mediaSize = PDFPageSizes[pageSize];
options.mediaSize = PDFPageSizes[pageSize];
} else {
throw new Error(`Unsupported pageSize: ${pageSize}`);
}
@@ -407,23 +417,23 @@ WebContents.prototype.loadFile = function (filePath, options = {}) {
}));
};
const addReplyToEvent = (event: any) => {
event.reply = (...args: any[]) => {
const addReplyToEvent = (event) => {
event.reply = (...args) => {
event.sender.sendToFrame(event.frameId, ...args);
};
};
const addReplyInternalToEvent = (event: any) => {
const addReplyInternalToEvent = (event) => {
Object.defineProperty(event, '_replyInternal', {
configurable: false,
enumerable: false,
value: (...args: any[]) => {
value: (...args) => {
event.sender._sendToFrameInternal(event.frameId, ...args);
}
});
};
const addReturnValueToEvent = (event: any) => {
const addReturnValueToEvent = (event) => {
Object.defineProperty(event, 'returnValue', {
set: (value) => event.sendReply([value]),
get: () => {}
@@ -433,30 +443,14 @@ const addReturnValueToEvent = (event: any) => {
// Add JavaScript wrappers for WebContents class.
WebContents.prototype._init = function () {
// The navigation controller.
const navigationController = new NavigationController(this);
this.loadURL = navigationController.loadURL.bind(navigationController);
this.getURL = navigationController.getURL.bind(navigationController);
this.stop = navigationController.stop.bind(navigationController);
this.reload = navigationController.reload.bind(navigationController);
this.reloadIgnoringCache = navigationController.reloadIgnoringCache.bind(navigationController);
this.canGoBack = navigationController.canGoBack.bind(navigationController);
this.canGoForward = navigationController.canGoForward.bind(navigationController);
this.canGoToIndex = navigationController.canGoToIndex.bind(navigationController);
this.canGoToOffset = navigationController.canGoToOffset.bind(navigationController);
this.clearHistory = navigationController.clearHistory.bind(navigationController);
this.goBack = navigationController.goBack.bind(navigationController);
this.goForward = navigationController.goForward.bind(navigationController);
this.goToIndex = navigationController.goToIndex.bind(navigationController);
this.goToOffset = navigationController.goToOffset.bind(navigationController);
this.getActiveIndex = navigationController.getActiveIndex.bind(navigationController);
this.length = navigationController.length.bind(navigationController);
NavigationController.call(this, this);
// Every remote callback from renderer process would add a listener to the
// render-view-deleted event, so ignore the listeners warning.
this.setMaxListeners(0);
// Dispatch IPC messages to the ipc module.
this.on('-ipc-message' as any, function (this: WebContentsInternal, event: any, internal: boolean, channel: string, args: any[]) {
this.on('-ipc-message', function (event, internal, channel, args) {
if (internal) {
addReplyInternalToEvent(event);
ipcMainInternal.emit(channel, event, ...args);
@@ -467,21 +461,21 @@ WebContents.prototype._init = function () {
}
});
this.on('-ipc-invoke' as any, function (event: any, internal: boolean, channel: string, args: any[]) {
event._reply = (result: any) => event.sendReply({ result });
event._throw = (error: Error) => {
this.on('-ipc-invoke', function (event, internal, channel, args) {
event._reply = (result) => event.sendReply({ result });
event._throw = (error) => {
console.error(`Error occurred in handler for '${channel}':`, error);
event.sendReply({ error: error.toString() });
};
const target = internal ? ipcMainInternal : ipcMain;
if ((target as any)._invokeHandlers.has(channel)) {
(target as any)._invokeHandlers.get(channel)(event, ...args);
if (target._invokeHandlers.has(channel)) {
target._invokeHandlers.get(channel)(event, ...args);
} else {
event._throw(`No handler registered for '${channel}'`);
}
});
this.on('-ipc-message-sync' as any, function (this: WebContentsInternal, event: any, internal: boolean, channel: string, args: any[]) {
this.on('-ipc-message-sync', function (event, internal, channel, args) {
addReturnValueToEvent(event);
if (internal) {
addReplyInternalToEvent(event);
@@ -493,15 +487,15 @@ WebContents.prototype._init = function () {
}
});
this.on('-ipc-ports' as any, function (event: any, internal: boolean, channel: string, message: any, ports: any[]) {
this.on('-ipc-ports', function (event, internal, channel, message, ports) {
event.ports = ports.map(p => new MessagePortMain(p));
ipcMain.emit(channel, event, message);
});
// Handle context menu action request from pepper plugin.
this.on('pepper-context-menu' as any, function (event: any, params: {x: number, y: number, menu: Array<(MenuItemConstructorOptions) | (MenuItem)>}, callback: () => void) {
this.on('pepper-context-menu', function (event, params, callback) {
// Access Menu via electron.Menu to prevent circular require.
const menu = require('electron').Menu.buildFromTemplate(params.menu);
const menu = electron.Menu.buildFromTemplate(params.menu);
menu.popup({
window: event.sender.getOwnerBrowserWindow(),
x: params.x,
@@ -519,14 +513,14 @@ WebContents.prototype._init = function () {
});
// The devtools requests the webContents to reload.
this.on('devtools-reload-page', function (this: WebContentsInternal) {
this.on('devtools-reload-page', function () {
this.reload();
});
if (this.getType() !== 'remote') {
// Make new windows requested by links behave like "window.open".
this.on('-new-window' as any, (event: any, url: string, frameName: string, disposition: string,
rawFeatures: string, referrer: string, postData: string) => {
this.on('-new-window', (event, url, frameName, disposition,
rawFeatures, referrer, postData) => {
const { options, webPreferences, additionalFeatures } = parseFeatures(rawFeatures);
const mergedOptions = {
show: true,
@@ -542,9 +536,9 @@ WebContents.prototype._init = function () {
// Create a new browser window for the native implementation of
// "window.open", used in sandbox and nativeWindowOpen mode.
this.on('-add-new-contents' as any, (event: any, webContents: WebContentsInternal, disposition: string,
userGesture: boolean, left: number, top: number, width: number, height: number, url: string, frameName: string,
referrer: string, rawFeatures: string, postData: string) => {
this.on('-add-new-contents', (event, webContents, disposition,
userGesture, left, top, width, height, url, frameName,
referrer, rawFeatures, postData) => {
if ((disposition !== 'foreground-tab' && disposition !== 'new-window' &&
disposition !== 'background-tab')) {
event.preventDefault();
@@ -567,7 +561,7 @@ WebContents.prototype._init = function () {
const prefs = this.getWebPreferences() || {};
if (prefs.webviewTag && prefs.contextIsolation) {
deprecate.log('Security Warning: A WebContents was just created with both webviewTag and contextIsolation enabled. This combination is fundamentally less secure and effectively bypasses the protections of contextIsolation. We strongly recommend you move away from webviews to OOPIF or BrowserView in order for your app to be more secure');
electron.deprecate.log('Security Warning: A WebContents was just created with both webviewTag and contextIsolation enabled. This combination is fundamentally less secure and effectively bypasses the protections of contextIsolation. We strongly recommend you move away from webviews to OOPIF or BrowserView in order for your app to be more secure');
}
}
@@ -575,7 +569,7 @@ WebContents.prototype._init = function () {
app.emit('login', event, this, ...args);
});
const event = process._linkedBinding('electron_browser_event').createEmpty();
const event = process.electronBinding('event').createEmpty();
app.emit('web-contents-created', event, this);
// Properties
@@ -612,25 +606,28 @@ WebContents.prototype._init = function () {
};
// Public APIs.
export function create (options = {}) {
return binding.create(options);
}
module.exports = {
create (options = {}) {
return binding.create(options);
},
export function fromId (id: string) {
return binding.fromId(id);
}
fromId (id) {
return binding.fromId(id);
},
export function getFocusedWebContents () {
let focused = null;
for (const contents of binding.getAllWebContents()) {
if (!contents.isFocused()) continue;
if (focused == null) focused = contents;
// Return webview web contents which may be embedded inside another
// web contents that is also reporting as focused
if (contents.getType() === 'webview') return contents;
getFocusedWebContents () {
let focused = null;
for (const contents of binding.getAllWebContents()) {
if (!contents.isFocused()) continue;
if (focused == null) focused = contents;
// Return webview web contents which may be embedded inside another
// web contents that is also reporting as focused
if (contents.getType() === 'webview') return contents;
}
return focused;
},
getAllWebContents () {
return binding.getAllWebContents();
}
return focused;
}
export function getAllWebContents () {
return binding.getAllWebContents();
}
};

View File

@@ -1,21 +1,23 @@
'use strict';
// This is a temporary shim to aid in transition from the old
// BrowserWindow-based extensions stuff to the new native-backed extensions
// API.
import { app, session, BrowserWindow, deprecate } from 'electron';
const { app, session, BrowserWindow, deprecate } = require('electron');
app.whenReady().then(function () {
const addExtension = function (srcDirectory: string) {
const addExtension = function (srcDirectory) {
return session.defaultSession.loadExtension(srcDirectory);
};
const removeExtension = function (name: string) {
const removeExtension = function (name) {
const extension = session.defaultSession.getAllExtensions().find(e => e.name === name);
if (extension) { session.defaultSession.removeExtension(extension.id); }
};
const getExtensions = function () {
const extensions: Record<string, any> = {};
const extensions = {};
session.defaultSession.getAllExtensions().forEach(e => {
extensions[e.name] = e;
});

View File

@@ -1,6 +1,6 @@
import { shell, Menu } from 'electron';
const v8Util = process._linkedBinding('electron_common_v8_util');
const v8Util = process.electronBinding('v8_util');
const isMac = process.platform === 'darwin';

View File

@@ -1,7 +1,4 @@
const {
createDesktopCapturer,
getMediaSourceIdForWebContents: getMediaSourceIdForWebContentsBinding
} = process._linkedBinding('electron_browser_desktop_capturer');
const { createDesktopCapturer } = process.electronBinding('desktop_capturer');
const deepEqual = (a: ElectronInternal.GetSourcesOptions, b: ElectronInternal.GetSourcesOptions) => JSON.stringify(a) === JSON.stringify(b);
@@ -80,7 +77,3 @@ export const getSourcesImpl = (event: Electron.IpcMainEvent | null, args: Electr
return getSources;
};
export const getMediaSourceIdForWebContents = (event: Electron.IpcMainEvent, webContentsId: number) => {
return getMediaSourceIdForWebContentsBinding(event.sender.id, webContentsId);
};

View File

@@ -59,7 +59,7 @@ function sanitizeOptionsForGuest (options) {
// Create a new guest instance.
const createGuest = function (embedder, params) {
if (webViewManager == null) {
webViewManager = process._linkedBinding('electron_browser_web_view_manager');
webViewManager = process.electronBinding('web_view_manager');
}
const guest = webContents.create({

View File

@@ -2,7 +2,7 @@
const electron = require('electron');
const { BrowserWindow } = electron;
const { isSameOrigin } = process._linkedBinding('electron_common_v8_util');
const { isSameOrigin } = process.electronBinding('v8_util');
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal');
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils');
const { parseFeatures } = require('@electron/internal/common/parse-features-string');
@@ -56,7 +56,7 @@ const mergeBrowserWindowOptions = function (embedder, options) {
let parentOptions = embedder.browserWindowOptions;
// if parent's visibility is available, that overrides 'show' flag (#12125)
const win = BrowserWindow.fromWebContents(embedder);
const win = BrowserWindow.fromWebContents(embedder.webContents);
if (win != null) {
parentOptions = {
...win.getBounds(),

View File

@@ -17,7 +17,7 @@ require('../common/reset-search-paths');
// Import common settings.
require('@electron/internal/common/init');
process._linkedBinding('electron_browser_event_emitter').setEventEmitterPrototype(EventEmitter.prototype);
process.electronBinding('event_emitter').setEventEmitterPrototype(EventEmitter.prototype);
if (process.platform === 'win32') {
// Redirect node's console to use our own implementations, since node can not

View File

@@ -1,6 +1,6 @@
import { ipcMainInternal } from './ipc-main-internal';
import type { WebContents, LoadURLOptions } from 'electron/main';
import { EventEmitter } from 'events';
'use strict';
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal');
// The history operation in renderer is redirected to browser.
ipcMainInternal.on('ELECTRON_NAVIGATION_CONTROLLER_GO_BACK', function (event) {
@@ -16,7 +16,7 @@ ipcMainInternal.on('ELECTRON_NAVIGATION_CONTROLLER_GO_TO_OFFSET', function (even
});
ipcMainInternal.on('ELECTRON_NAVIGATION_CONTROLLER_LENGTH', function (event) {
event.returnValue = (event.sender as any).length();
event.returnValue = event.sender.length();
});
// JavaScript implementation of Chromium's NavigationController.
@@ -24,14 +24,9 @@ ipcMainInternal.on('ELECTRON_NAVIGATION_CONTROLLER_LENGTH', function (event) {
// control on user land, and only rely on WebContents.loadURL for navigation.
// This helps us avoid Chromium's various optimizations so we can ensure renderer
// process is restarted everytime.
export class NavigationController extends EventEmitter {
currentIndex: number = -1;
inPageIndex: number = -1;
pendingIndex: number = -1;
history: string[] = [];
constructor (private webContents: WebContents) {
super();
const NavigationController = (function () {
function NavigationController (webContents) {
this.webContents = webContents;
this.clearHistory();
// webContents may have already navigated to a page.
@@ -39,7 +34,7 @@ export class NavigationController extends EventEmitter {
this.currentIndex++;
this.history.push(this.webContents._getURL());
}
this.webContents.on('navigation-entry-committed' as any, (event: any, url: string, inPage: boolean, replaceEntry: boolean) => {
this.webContents.on('navigation-entry-committed', (event, url, inPage, replaceEntry) => {
if (this.inPageIndex > -1 && !inPage) {
// Navigated to a new page, clear in-page mark.
this.inPageIndex = -1;
@@ -64,16 +59,16 @@ export class NavigationController extends EventEmitter {
});
}
loadURL (url: string, options?: LoadURLOptions): Promise<void> {
NavigationController.prototype.loadURL = function (url, options) {
if (options == null) {
options = {};
}
const p = new Promise<void>((resolve, reject) => {
const p = new Promise((resolve, reject) => {
const resolveAndCleanup = () => {
removeListeners();
resolve();
};
const rejectAndCleanup = (errorCode: number, errorDescription: string, url: string) => {
const rejectAndCleanup = (errorCode, errorDescription, url) => {
const err = new Error(`${errorDescription} (${errorCode}) loading '${typeof url === 'string' ? url.substr(0, 2048) : url}'`);
Object.assign(err, { errno: errorCode, code: errorDescription, url });
removeListeners();
@@ -82,14 +77,14 @@ export class NavigationController extends EventEmitter {
const finishListener = () => {
resolveAndCleanup();
};
const failListener = (event: any, errorCode: number, errorDescription: string, validatedURL: string, isMainFrame: boolean) => {
const failListener = (event, errorCode, errorDescription, validatedURL, isMainFrame, frameProcessId, frameRoutingId) => {
if (isMainFrame) {
rejectAndCleanup(errorCode, errorDescription, validatedURL);
}
};
let navigationStarted = false;
const navigationListener = (event: any, url: string, isSameDocument: boolean, isMainFrame: boolean) => {
const navigationListener = (event, url, isSameDocument, isMainFrame, frameProcessId, frameRoutingId, navigationId) => {
if (isMainFrame) {
if (navigationStarted && !isSameDocument) {
// the webcontents has started another unrelated navigation in the
@@ -134,58 +129,58 @@ export class NavigationController extends EventEmitter {
this.webContents._loadURL(url, options);
this.webContents.emit('load-url', url, options);
return p;
}
};
getURL () {
NavigationController.prototype.getURL = function () {
if (this.currentIndex === -1) {
return '';
} else {
return this.history[this.currentIndex];
}
}
};
stop () {
NavigationController.prototype.stop = function () {
this.pendingIndex = -1;
return this.webContents._stop();
}
};
reload () {
NavigationController.prototype.reload = function () {
this.pendingIndex = this.currentIndex;
return this.webContents._loadURL(this.getURL(), {});
}
};
reloadIgnoringCache () {
NavigationController.prototype.reloadIgnoringCache = function () {
this.pendingIndex = this.currentIndex;
return this.webContents._loadURL(this.getURL(), {
extraHeaders: 'pragma: no-cache\n',
reloadIgnoringCache: true
} as any);
}
});
};
canGoBack () {
NavigationController.prototype.canGoBack = function () {
return this.getActiveIndex() > 0;
}
};
canGoForward () {
NavigationController.prototype.canGoForward = function () {
return this.getActiveIndex() < this.history.length - 1;
}
};
canGoToIndex (index: number) {
NavigationController.prototype.canGoToIndex = function (index) {
return index >= 0 && index < this.history.length;
}
};
canGoToOffset (offset: number) {
NavigationController.prototype.canGoToOffset = function (offset) {
return this.canGoToIndex(this.currentIndex + offset);
}
};
clearHistory () {
NavigationController.prototype.clearHistory = function () {
this.history = [];
this.currentIndex = -1;
this.pendingIndex = -1;
this.inPageIndex = -1;
}
};
goBack () {
NavigationController.prototype.goBack = function () {
if (!this.canGoBack()) {
return;
}
@@ -195,9 +190,9 @@ export class NavigationController extends EventEmitter {
} else {
return this.webContents._loadURL(this.history[this.pendingIndex], {});
}
}
};
goForward () {
NavigationController.prototype.goForward = function () {
if (!this.canGoForward()) {
return;
}
@@ -207,17 +202,17 @@ export class NavigationController extends EventEmitter {
} else {
return this.webContents._loadURL(this.history[this.pendingIndex], {});
}
}
};
goToIndex (index: number) {
NavigationController.prototype.goToIndex = function (index) {
if (!this.canGoToIndex(index)) {
return;
}
this.pendingIndex = index;
return this.webContents._loadURL(this.history[this.pendingIndex], {});
}
};
goToOffset (offset: number) {
NavigationController.prototype.goToOffset = function (offset) {
if (!this.canGoToOffset(offset)) {
return;
}
@@ -228,17 +223,21 @@ export class NavigationController extends EventEmitter {
} else {
return this.goToIndex(pendingIndex);
}
}
};
getActiveIndex () {
NavigationController.prototype.getActiveIndex = function () {
if (this.pendingIndex === -1) {
return this.currentIndex;
} else {
return this.pendingIndex;
}
}
};
length () {
NavigationController.prototype.length = function () {
return this.history.length;
}
}
};
return NavigationController;
})();
module.exports = NavigationController;

View File

@@ -2,7 +2,7 @@
import { WebContents } from 'electron';
const v8Util = process._linkedBinding('electron_common_v8_util');
const v8Util = process.electronBinding('v8_util');
const getOwnerKey = (webContents: WebContents, contextId: string) => {
return `${webContents.id}-${contextId}`;
@@ -51,11 +51,19 @@ class ObjectsRegistry {
// Dereference an object according to its ID.
// Note that an object may be double-freed (cleared when page is reloaded, and
// then garbage collected in old page).
remove (webContents: WebContents, contextId: string, id: number) {
// rendererSideRefCount is the ref count that the renderer process reported
// at time of GC if this is different to the number of references we sent to
// the given owner then a GC occurred between a ref being sent and the value
// being pulled out of the weak map.
// In this case we decrement out ref count and do not delete the stored
// object
// For more details on why we do renderer side ref counting see
// https://github.com/electron/electron/pull/17464
remove (webContents: WebContents, contextId: string, id: number, rendererSideRefCount: number) {
const ownerKey = getOwnerKey(webContents, contextId);
const owner = this.owners[ownerKey];
if (owner && owner.has(id)) {
const newRefCount = owner.get(id)! - 1;
const newRefCount = owner.get(id)! - rendererSideRefCount;
// Only completely remove if the number of references GCed in the
// renderer is the same as the number of references we sent them

View File

@@ -1,60 +1,38 @@
'use strict';
import * as electron from 'electron';
import { EventEmitter } from 'events';
import objectsRegistry from './objects-registry';
import { ipcMainInternal } from '../ipc-main-internal';
import { isPromise, isSerializableObject, deserialize, serialize } from '../../common/type-utils';
import type { MetaTypeFromRenderer, ObjectMember, MetaType, ObjProtoDescriptor } from '../../common/remote/types';
import { isPromise, isSerializableObject, deserialize, serialize } from '@electron/internal/common/type-utils';
import { Size } from 'electron/main';
const v8Util = process._linkedBinding('electron_common_v8_util');
const eventBinding = process._linkedBinding('electron_browser_event');
const features = process._linkedBinding('electron_common_features');
const { NativeImage } = process._linkedBinding('electron_common_native_image');
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');
}
const hasProp = {}.hasOwnProperty;
// The internal properties of Function.
const FUNCTION_PROPERTIES = [
'length', 'name', 'arguments', 'caller', 'prototype'
];
type RendererFunctionId = [string, number] // [contextId, funcId]
type FinalizerInfo = { id: RendererFunctionId, webContents: electron.WebContents, frameId: number };
type WeakRef<T> = { deref(): T | undefined }
type CallIntoRenderer = (...args: any[]) => void
// The remote functions in renderer processes.
const rendererFunctionCache = new Map<string, WeakRef<CallIntoRenderer>>();
// eslint-disable-next-line no-undef
const finalizationRegistry = new (globalThis as any).FinalizationRegistry((fi: FinalizerInfo) => {
const mapKey = fi.id[0] + '~' + fi.id[1];
const ref = rendererFunctionCache.get(mapKey);
if (ref !== undefined && ref.deref() === undefined) {
rendererFunctionCache.delete(mapKey);
if (!fi.webContents.isDestroyed()) { fi.webContents.sendToFrame(fi.frameId, 'ELECTRON_RENDERER_RELEASE_CALLBACK', fi.id[0], fi.id[1]); }
}
});
// id => Function
const rendererFunctions = v8Util.createDoubleIDWeakMap<(...args: any[]) => void>();
function getCachedRendererFunction (id: RendererFunctionId): CallIntoRenderer | undefined {
const mapKey = id[0] + '~' + id[1];
const ref = rendererFunctionCache.get(mapKey);
if (ref !== undefined) {
const deref = ref.deref();
if (deref !== undefined) return deref;
}
}
function setCachedRendererFunction (id: RendererFunctionId, wc: electron.WebContents, frameId: number, value: CallIntoRenderer) {
// eslint-disable-next-line no-undef
const wr = new (globalThis as any).WeakRef(value) as WeakRef<CallIntoRenderer>;
const mapKey = id[0] + '~' + id[1];
rendererFunctionCache.set(mapKey, wr);
finalizationRegistry.register(value, {
id,
webContents: wc,
frameId
} as FinalizerInfo);
return value;
type ObjectMember = {
name: string,
value?: any,
enumerable?: boolean,
writable?: boolean,
type?: 'method' | 'get'
}
// Return the description of object's members:
@@ -82,6 +60,11 @@ const getObjectMembers = function (object: any): ObjectMember[] {
});
};
type ObjProtoDescriptor = {
members: ObjectMember[],
proto: ObjProtoDescriptor
} | null
// Return the description of object's prototype.
const getObjectPrototype = function (object: any): ObjProtoDescriptor {
const proto = Object.getPrototypeOf(object);
@@ -92,42 +75,76 @@ const getObjectPrototype = function (object: any): ObjProtoDescriptor {
};
};
type MetaType = {
type: 'number',
value: number
} | {
type: 'boolean',
value: boolean
} | {
type: 'string',
value: string
} | {
type: 'bigint',
value: bigint
} | {
type: 'symbol',
value: symbol
} | {
type: 'undefined',
value: undefined
} | {
type: 'object' | 'function',
name: string,
members: ObjectMember[],
proto: ObjProtoDescriptor,
id: number,
} | {
type: 'value',
value: any,
} | {
type: 'buffer',
value: Uint8Array,
} | {
type: 'array',
members: MetaType[]
} | {
type: 'error',
value: Error,
members: ObjectMember[]
} | {
type: 'promise',
then: MetaType
} | {
type: 'nativeimage'
value: electron.NativeImage
}
// Convert a real value into meta data.
const valueToMeta = function (sender: electron.WebContents, contextId: string, value: any, optimizeSimpleObject = false): MetaType {
// Determine the type of value.
let type: MetaType['type'];
switch (typeof value) {
case 'object':
// 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) {
type = 'error';
} else if (isSerializableObject(value)) {
type = 'value';
} else if (isPromise(value)) {
type = 'promise';
} else if (Object.prototype.hasOwnProperty.call(value, 'callee') && value.length != null) {
// Treat the arguments object as array.
type = 'array';
} else if (optimizeSimpleObject && v8Util.getHiddenValue(value, 'simple')) {
// Treat simple objects as value.
type = 'value';
} else {
type = 'object';
}
break;
case 'function':
type = 'function';
break;
default:
let type: MetaType['type'] = typeof value;
if (type === 'object') {
// 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) {
type = 'error';
} else if (isSerializableObject(value)) {
type = 'value';
break;
} else if (isPromise(value)) {
type = 'promise';
} else if (hasProp.call(value, 'callee') && value.length != null) {
// Treat the arguments object as array.
type = 'array';
} else if (optimizeSimpleObject && v8Util.getHiddenValue(value, 'simple')) {
// Treat simple objects as value.
type = 'value';
}
}
// Fill the meta object according to value's type.
@@ -207,6 +224,46 @@ const removeRemoteListenersAndLogWarning = (sender: any, callIntoRenderer: (...a
console.warn(message);
};
type MetaTypeFromRenderer = {
type: 'value',
value: any
} | {
type: 'remote-object',
id: number
} | {
type: 'array',
value: MetaTypeFromRenderer[]
} | {
type: 'buffer',
value: Uint8Array
} | {
type: 'promise',
then: MetaTypeFromRenderer
} | {
type: 'object',
name: string,
members: {
name: string,
value: MetaTypeFromRenderer
}[]
} | {
type: 'function-with-return-value',
value: MetaTypeFromRenderer
} | {
type: 'function',
id: number,
location: string,
length: number
} | {
type: 'nativeimage',
value: {
size: Size,
buffer: Buffer,
scaleFactor: number,
dataURL: string
}[]
}
const fakeConstructor = (constructor: Function, name: string) =>
new Proxy(Object, {
get (target, prop, receiver) {
@@ -258,8 +315,9 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
const objectId: [string, number] = [contextId, meta.id];
// Cache the callbacks in renderer.
const cachedFunction = getCachedRendererFunction(objectId);
if (cachedFunction !== undefined) { return cachedFunction; }
if (rendererFunctions.has(objectId)) {
return rendererFunctions.get(objectId);
}
const callIntoRenderer = function (this: any, ...args: any[]) {
let succeed = false;
@@ -273,7 +331,8 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
v8Util.setHiddenValue(callIntoRenderer, 'location', meta.location);
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length });
setCachedRendererFunction(objectId, sender, frameId, callIntoRenderer);
v8Util.setRemoteCallbackFreer(callIntoRenderer, frameId, contextId, meta.id, sender);
rendererFunctions.set(objectId, callIntoRenderer);
return callIntoRenderer;
}
default:
@@ -284,13 +343,13 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
};
const isRemoteModuleEnabledImpl = function (contents: electron.WebContents) {
const webPreferences = contents.getLastWebPreferences() || {};
const webPreferences = (contents as any).getLastWebPreferences() || {};
return webPreferences.enableRemoteModule != null ? !!webPreferences.enableRemoteModule : false;
};
const isRemoteModuleEnabledCache = new WeakMap();
export const isRemoteModuleEnabled = function (contents: electron.WebContents) {
const isRemoteModuleEnabled = function (contents: electron.WebContents) {
if (!isRemoteModuleEnabledCache.has(contents)) {
isRemoteModuleEnabledCache.set(contents, isRemoteModuleEnabledImpl(contents));
}
@@ -338,12 +397,11 @@ const logStack = function (contents: electron.WebContents, code: string, stack:
handleRemoteCommand('ELECTRON_BROWSER_WRONG_CONTEXT_ERROR', function (event, contextId, passedContextId, id) {
const objectId: [string, number] = [passedContextId, id];
const cachedFunction = getCachedRendererFunction(objectId);
if (cachedFunction === undefined) {
if (!rendererFunctions.has(objectId)) {
// Do nothing if the error has already been reported before.
return;
}
removeRemoteListenersAndLogWarning(event.sender, cachedFunction);
removeRemoteListenersAndLogWarning(event.sender, rendererFunctions.get(objectId)!);
});
handleRemoteCommand('ELECTRON_BROWSER_REQUIRE', function (event, contextId, moduleName, stack) {
@@ -499,10 +557,14 @@ handleRemoteCommand('ELECTRON_BROWSER_MEMBER_GET', function (event, contextId, i
return valueToMeta(event.sender, contextId, obj[name]);
});
handleRemoteCommand('ELECTRON_BROWSER_DEREFERENCE', function (event, contextId, id) {
objectsRegistry.remove(event.sender, contextId, id);
handleRemoteCommand('ELECTRON_BROWSER_DEREFERENCE', function (event, contextId, id, rendererSideRefCount) {
objectsRegistry.remove(event.sender, contextId, id, rendererSideRefCount);
});
handleRemoteCommand('ELECTRON_BROWSER_CONTEXT_RELEASE', (event, contextId) => {
objectsRegistry.clear(event.sender, contextId);
});
module.exports = {
isRemoteModuleEnabled
};

View File

@@ -1,15 +1,17 @@
import * as electron from 'electron';
import * as fs from 'fs';
import { ipcMainInternal } from './ipc-main-internal';
import * as ipcMainUtils from './ipc-main-internal-utils';
import * as guestViewManager from './guest-view-manager';
import * as typeUtils from '../common/type-utils';
import { IpcMainInvokeEvent } from 'electron/main';
'use strict';
const eventBinding = process._linkedBinding('electron_browser_event');
const clipboard = process._linkedBinding('electron_common_clipboard');
const electron = require('electron');
const fs = require('fs');
const emitCustomEvent = function (contents: electron.WebContents, eventName: string, ...args: any[]) {
const eventBinding = process.electronBinding('event');
const clipboard = process.electronBinding('clipboard');
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');
const typeUtils = require('@electron/internal/common/type-utils');
const emitCustomEvent = function (contents, eventName, ...args) {
const event = eventBinding.createWithSender(contents);
electron.app.emit(eventName, event, contents, ...args);
@@ -18,14 +20,14 @@ const emitCustomEvent = function (contents: electron.WebContents, eventName: str
return event;
};
const logStack = function (contents: electron.WebContents, code: string, stack: string) {
const logStack = function (contents, code, stack) {
if (stack) {
console.warn(`WebContents (${contents.id}): ${code}`, stack);
}
};
// Implements window.close()
ipcMainInternal.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event: ElectronInternal.IpcMainInternalEvent) {
ipcMainInternal.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event) {
const window = event.sender.getOwnerBrowserWindow();
if (window) {
window.close();
@@ -33,7 +35,7 @@ ipcMainInternal.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event: ElectronInt
event.returnValue = null;
});
ipcMainInternal.handle('ELECTRON_BROWSER_GET_LAST_WEB_PREFERENCES', function (event: IpcMainInvokeEvent) {
ipcMainInternal.handle('ELECTRON_BROWSER_GET_LAST_WEB_PREFERENCES', function (event) {
return event.sender.getLastWebPreferences();
});
@@ -49,18 +51,18 @@ const allowedClipboardMethods = (() => {
}
})();
ipcMainUtils.handleSync('ELECTRON_BROWSER_CLIPBOARD_SYNC', function (event: IpcMainInvokeEvent, method: string, ...args: any[]) {
ipcMainUtils.handleSync('ELECTRON_BROWSER_CLIPBOARD_SYNC', function (event, method, ...args) {
if (!allowedClipboardMethods.has(method)) {
throw new Error(`Invalid method: ${method}`);
}
return typeUtils.serialize((electron.clipboard as any)[method](...typeUtils.deserialize(args)));
return typeUtils.serialize(electron.clipboard[method](...typeUtils.deserialize(args)));
});
if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
const desktopCapturer = require('@electron/internal/browser/desktop-capturer');
ipcMainInternal.handle('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', async function (event: IpcMainInvokeEvent, options: Electron.SourcesOptions, stack: string) {
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');
@@ -71,17 +73,13 @@ if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
return typeUtils.serialize(await desktopCapturer.getSourcesImpl(event, options));
});
ipcMainInternal.handle('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_MEDIA_SOURCE_ID_FOR_WEB_CONTENTS', function (event: IpcMainInvokeEvent, webContentsId: number) {
return desktopCapturer.getMediaSourceIdForWebContents(event, webContentsId);
});
}
const isRemoteModuleEnabled = BUILDFLAG(ENABLE_REMOTE_MODULE)
? require('@electron/internal/browser/remote/server').isRemoteModuleEnabled
: () => false;
const getPreloadScript = async function (preloadPath: string) {
const getPreloadScript = async function (preloadPath) {
let preloadSrc = null;
let preloadError = null;
try {
@@ -92,7 +90,7 @@ const getPreloadScript = async function (preloadPath: string) {
return { preloadPath, preloadSrc, preloadError };
};
ipcMainUtils.handleSync('ELECTRON_BROWSER_SANDBOX_LOAD', async function (event: IpcMainInvokeEvent) {
ipcMainUtils.handleSync('ELECTRON_BROWSER_SANDBOX_LOAD', async function (event) {
const preloadPaths = event.sender._getPreloadPaths();
const webPreferences = event.sender.getLastWebPreferences() || {};
@@ -113,7 +111,7 @@ ipcMainUtils.handleSync('ELECTRON_BROWSER_SANDBOX_LOAD', async function (event:
};
});
ipcMainInternal.on('ELECTRON_BROWSER_PRELOAD_ERROR', function (event: ElectronInternal.IpcMainInternalEvent, preloadPath: string, error: Error) {
ipcMainInternal.on('ELECTRON_BROWSER_PRELOAD_ERROR', function (event, preloadPath, error) {
event.sender.emit('preload-error', event, preloadPath, error);
});
@@ -129,7 +127,7 @@ ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_GET_UPLOAD_TO_SERVER', () => {
return electron.crashReporter.getUploadToServer();
});
ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_SET_UPLOAD_TO_SERVER', (event: IpcMainInvokeEvent, uploadToServer: boolean) => {
ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_SET_UPLOAD_TO_SERVER', (event, uploadToServer) => {
return electron.crashReporter.setUploadToServer(uploadToServer);
});

View File

@@ -1,11 +1,13 @@
const clipboard = process._linkedBinding('electron_common_clipboard');
'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: keyof Electron.Clipboard) {
return (...args: any[]) => {
const makeRemoteMethod = function (method) {
return (...args) => {
args = typeUtils.serialize(args);
const result = ipcRendererUtils.invokeSync('ELECTRON_BROWSER_CLIPBOARD_SYNC', method, ...args);
return typeUtils.deserialize(result);
@@ -14,7 +16,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) as (keyof Electron.Clipboard)[]) {
for (const method of Object.keys(clipboard)) {
clipboard[method] = makeRemoteMethod(method);
}
} else if (process.platform === 'darwin') {
@@ -24,4 +26,4 @@ if (process.type === 'renderer') {
}
}
export default clipboard;
module.exports = clipboard;

View File

@@ -55,12 +55,12 @@ const deprecate: ElectronInternal.DeprecationUtil = {
};
},
moveAPI<T extends Function> (fn: T, oldUsage: string, newUsage: string): T {
moveAPI: (fn: Function, oldUsage: string, newUsage: string) => {
const warn = warnOnce(oldUsage, newUsage);
return function (this: any) {
warn();
return fn.apply(this, arguments);
} as any;
};
},
// change the name of an event
@@ -76,6 +76,23 @@ const deprecate: ElectronInternal.DeprecationUtil = {
});
},
// deprecate a getter/setter function pair in favor of a property
fnToProperty: (prototype: any, prop: string, getter: string, setter?: string) => {
const withWarnOnce = function (obj: any, key: any, oldName: string, newName: string) {
const warn = warnOnce(oldName, newName);
const method = obj[key];
return function (this: any, ...args: any) {
warn();
return method.apply(this, args);
};
};
prototype[getter.substr(1)] = withWarnOnce(prototype, getter, `${getter.substr(1)} function`, `${prop} property`);
if (setter) {
prototype[setter.substr(1)] = withWarnOnce(prototype, setter, `${setter.substr(1)} function`, `${prop} property`);
}
},
// remove a property with no replacement
removeProperty: (o, removedName, onlyForValues) => {
// if the property's already been removed, warn about it

View File

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

View File

@@ -1,3 +0,0 @@
const { nativeImage } = process._linkedBinding('electron_common_native_image');
export default nativeImage;

3
lib/common/api/shell.js Normal file
View File

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

View File

@@ -1 +0,0 @@
export default process._linkedBinding('electron_common_shell');

View File

@@ -1,4 +1,6 @@
'use strict';
/* global require */
// Monkey-patch the fs module.
require('electron/js2c/asar').wrapFsWithAsar(require('fs'));

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