Compare commits

..

147 Commits

Author SHA1 Message Date
Electron Bot
1c791f9056 Bump v9.0.0-beta.15 2020-04-09 08:33:07 -07:00
Jeremy Apthorp
359110a651 ci: auto-3way patches and detect changes (#23031)
* ci: auto-3way patches and detect changes (#22976)

* bust cache

* update-index || true

* update patches

* lint

* idk what is up with lint

* idek

* update patches

Co-authored-by: Electron Bot <anonymous@electronjs.org>
2020-04-09 11:06:57 -04:00
Jeremy Apthorp
7894ae9c01 chore: bump chromium to 83.0.4102.3 (#22941)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: Andy Locascio <andy@slack-corp.com>
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-04-08 14:37:31 -07:00
trop[bot]
ab41460616 fix: nullptr check when closing windows (#23023) 2020-04-07 22:10:28 -07:00
trop[bot]
8a4d41cd46 build: set merge=union for .patches (#22991)
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-04-07 09:55:17 -07:00
trop[bot]
41f33edd9e fix: webframe crashes for removed render frame (#22949)
* fix: webframe crashes for removed render frame

* Make errors more descriptive

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-04-06 11:38:44 -07:00
Electron Bot
21f78af43f Bump v9.0.0-beta.14 2020-04-06 08:32:24 -07:00
Electron Bot
c09bfb5a79 chore: bump chromium in DEPS to 82.0.4085.27 (#22932) 2020-04-02 17:53:33 -07:00
Electron Bot
fb5871ccf0 Bump v9.0.0-beta.13 2020-04-02 08:31:38 -07:00
Cheng Zhao
f255d47073 fix: webRequest module should work with file:// protocol (9-x-y) (#22919)
* fix: webRequest module should work with file:// protocol

* test: do not trigger unhandled promise rejections
2020-04-01 13:36:24 -07:00
trop[bot]
050844dc38 fix: screen module should still be creatable if the first create is before the ready event (#22912)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-04-01 11:37:12 -07:00
trop[bot]
317f1a3d3a fix: ensure standard schemes are registered in nw service process (#22917)
* fix: ensure standard schemes are registered in nw service process

Refs https://github.com/electron/electron/pull/20546

* chore: add test

* chore: apply suggestions from code review

Co-Authored-By: Jeremy Apthorp <jeremya@chromium.org>

Co-authored-by: deepak1556 <hop2deep@gmail.com>
Co-authored-by: Jeremy Apthorp <jeremya@chromium.org>
2020-03-31 21:25:45 -07:00
trop[bot]
b4675ce0ae fix: dialog fails to show after modal close (#22890)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-03-31 14:50:11 -07:00
trop[bot]
3f6227c61a fix: propagate preferred color scheme to the renderer (#22900)
* fix: do not crash if the window is closed syncronously with a nativeTheme change

* fix: propogate preferred color scheme to the renderer and keep it up to date

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-03-31 14:46:15 -07:00
Electron Bot
bfc069e5c0 Bump v9.0.0-beta.12 2020-03-30 08:32:46 -07:00
trop[bot]
6cb495034e fix: don't try to hide host which has set flag disable_hidden_ (#22852)
Lack of this change will lead to freeze after call to hide/show
on window which has set flag disable_hidden_. To reproduce the
problem it's necessary to create some number of windows (how many
it depends on number of windows being cached by Chromium's
FrameEvictionManager).

Co-authored-by: Cezary Kulakowski <cezary@openfin.co>
2020-03-27 11:42:20 -07:00
trop[bot]
6d2cf47797 fix: heap-use-after-free in tray.popUpContextMenu (#22855)
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-03-27 15:34:18 +09:00
Electron Bot
e06880a90e Bump v9.0.0-beta.11 2020-03-26 08:32:00 -07:00
trop[bot]
0600420bac fix: don't allow window to go behind menu bar on mac (#22828)
Co-authored-by: Cezary Kulakowski <cezary@openfin.co>
2020-03-25 10:45:32 -05:00
trop[bot]
a6ff42c190 fix: workaround for hang when preventDefault-ing nativeWindowOpen (#22750)
* fix: enable workaround for nativeWindowOpen hang

* add test

* test: ensure window doesn't leak into other test

* update to use new webcontents delegate methods

Co-authored-by: Andy Locascio <andy@slack-corp.com>
2020-03-25 10:40:12 +09:00
trop[bot]
969579070f refactor: migrate base::ThreadPool() as trait to base::ThreadPool:: API (#22607) 2020-03-24 15:09:28 -07:00
trop[bot]
9ee656f856 build: fix missing pdf dep in chromium_src (#22814)
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-03-24 09:00:51 -04:00
Samuel Attard
7e4475cf51 Revert "fix: better window hierarchy checks"
This reverts commit 792fe833d1.
2020-03-23 19:35:21 -07:00
Samuel Attard
79d9bd3a29 Revert "Bump v9.0.0-beta.11"
This reverts commit 50debf8595.
2020-03-23 19:35:12 -07:00
Electron Bot
50debf8595 Bump v9.0.0-beta.11 2020-03-23 15:30:19 -07:00
Electron Bot
2d68a4d2ee Revert "Bump v9.0.0-beta.11"
This reverts commit 6ce0062c0e.
2020-03-23 15:25:54 -07:00
Electron Bot
6ce0062c0e Bump v9.0.0-beta.11 2020-03-23 14:27:00 -07:00
Samuel Attard
86aa0dfc45 build: fix beta version bumper logic for betas beyond 10 2020-03-23 14:25:54 -07:00
Samuel Attard
792fe833d1 fix: better window hierarchy checks 2020-03-23 14:13:00 -07:00
Samuel Attard
9b14ae770d feat: add support for net requests to use the session cookie store (#22806)
* chore: refactor all the net specs to be async with better error handling (#22731)

* chore: fix net specs when rerunning locally (#22745)

* feat: add support for net requests to use the session cookie store (#22704)

* fix: allow net requests to use Same-Site cookies (#22788)
2020-03-23 10:53:40 -07:00
Samuel Attard
5a34ad4e21 build: enable JS semicolons (#22785) 2020-03-23 09:18:28 -07:00
Eryk Rakowski
edd7e97dd9 feat(extensions): add more properties to extension object (#22595) 2020-03-21 10:28:05 +09:00
Electron Bot
b92734d912 chore: bump chromium to 82.0.4085.14 (9-x-y) (#22743) 2020-03-20 15:58:36 -07:00
Shelley Vohr
dc25ad2ef0 chore: update app module property support (#22747) 2020-03-20 16:09:47 +09:00
Charles Kerr
54a8258c1c refactor: omit duplicates from app's x11 icon list (#22736) 2020-03-19 14:12:07 -07:00
trop[bot]
02eff88e1b chore: revert deprecated WebContents properties (#22682) 2020-03-19 14:11:41 -07:00
trop[bot]
09ca564bf4 fix: prevent crash in ListValue v8 converter when conversion fails (#22759) 2020-03-19 14:02:31 -07:00
trop[bot]
54e31956f8 chore: more modules to dual prop/fn support (#22734) 2020-03-19 09:27:39 -07:00
Electron Bot
c6539f0d01 Bump v9.0.0-beta.10 2020-03-19 08:31:11 -07:00
trop[bot]
bef8448393 build: auto-generate the codesigning cert used for macOS CI testing runs (#22762)
* build: auto-generate the codesigning cert used for macOS CI testing runs

* build: give the cert ALL the trust values

* chore: also import public key

* idek

Co-authored-by: Samuel Attard <sattard@slack-corp.com>
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-03-19 16:34:57 +09:00
trop[bot]
27619e8ab0 test: no need to loadURL in menu test (#22765)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-03-19 16:33:57 +09:00
trop[bot]
89c23f313f fix: crash when destroying WebContentsView during GC (#22764)
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-03-19 16:33:22 +09:00
Cheng Zhao
a9b9016b99 fix: avoid double-free in TrackableObject (#22768) 2020-03-19 16:32:46 +09:00
trop[bot]
f1c1542958 chore: support props/fns for BrowserWindow (#22733) 2020-03-18 19:53:11 -07:00
Сковорода Никита Андреевич
cb90ef47bb feat: add disableDialogs option to WebPreferences (#22664)
Allows to disable dialogs completely in a similar way of how safeDialogs option can be used. Overrides safeDialogs option.
2020-03-18 20:02:29 -04:00
trop[bot]
a345fe2b4f fix: persist maximizable state through theme change (#22724)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-03-18 09:39:00 +09:00
trop[bot]
0cf02dd78b fix: remove bad usages of for-in and guard against it (#22727)
* fix: remove bad usages of for-in and guard against it

* Apply suggestions from code review

Co-Authored-By: Samuel Maddock <samuel.maddock@gmail.com>

* Apply suggestions from code review

Co-Authored-By: Jeremy Apthorp <jeremya@chromium.org>

* Update remote.js

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: Samuel Attard <sattard@slack-corp.com>
Co-authored-by: Samuel Maddock <samuel.maddock@gmail.com>
Co-authored-by: Jeremy Apthorp <jeremya@chromium.org>
2020-03-18 09:38:26 +09:00
Electron Bot
3d941fc464 chore: bump chromium to 82.0.4085.10 (9-x-y) (#22506)
* chore: bump chromium in DEPS to 82.0.4076.1

* update patches

* chore: bump chromium in DEPS to 82.0.4077.1

* update v8 patches

* Remove deprecated wasm module type check

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

* chore: bump chromium in DEPS to 82.0.4078.0

* chore: bump chromium in DEPS to 82.0.4079.0

* chore: bump chromium in DEPS to 82.0.4080.0

* chore: bump chromium in DEPS to 82.0.4080.1

* chore: bump chromium in DEPS to 82.0.4081.2

* Update patches

* chore: bump chromium in DEPS to 82.0.4082.1

* Remove cursor_types.h in favor of cursor_type.mojom

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

* Refactor extensions report in management disclosure page

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

* Rename an old referrer policy value

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

* Fixup compiler errors

* Move GLHelper to gpu::

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

* [api] Remove deprecated wasm module type check

https://chromium-review.googlesource.com/c/v8/v8/+/2033170
(cherry picked from commit 937988e6ce)

* Replace blink::WebCursorInfo with ui::Cursor

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

* DownloadURLParameters: Remove NetworkIsolationKey parameter.

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

* Convert FrameHostMsg_UpdateFaviconURL to mojo

https://chromium-review.googlesource.com/c/chromium/src/+/2043181
(cherry picked from commit 11b9c27eee)

* Merge ui::ContextFactoryPrivate with ui::ContextFactory

https://chromium-review.googlesource.com/c/chromium/src/+/2047728
(cherry picked from commit 176876f243)

* fix pdf viewer tests by binding more mojo things

(cherry picked from commit 74def418df)

* chore: bump chromium in DEPS to 82.0.4083.1

* Update electron_swiftshader_binaries deps

https://chromium-review.googlesource.com/c/chromium/src/+/2056931
(cherry picked from commit 312f11129f)

* Update patches

* Use Promise with RequestPointerLock calls

https://chromium-review.googlesource.com/c/chromium/src/+/2069199
(cherry picked from commit 34350db4bd)

* chore: bump chromium in DEPS to 82.0.4084.1

* Replace content::CursorInfo with ui::Cursor

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

* Convert MaterialDesignController to a true singleton.

https://chromium-review.googlesource.com/c/chromium/src/+/2090877
(cherry picked from commit 21ced9206d)

* Drop WebContentsView::RenderViewCreated hook

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

* Update patches

* Splitting context_menu_params.h into separate browser VS common parts.

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

* Fix DCHECK on OnThemeChanged()

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

* chore: bump chromium in DEPS to 82.0.4085.1

* chore: bump chromium in DEPS to 82.0.4085.5

* chore: bump chromium in DEPS to 82.0.4085.7

* chore: bump chromium in DEPS to 82.0.4085.9

* Add debugging for TAB tests

* update patches

* fix: add patch to fix linux arm build (#22523)


(cherry picked from commit 479354e721)

* chore: bump chromium in DEPS to 82.0.4085.10

* Check PointerLock requests for new options and update accordingly

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

* Update for changes from master roller review

* FIXME: skip Menu.setApplicationMenu(null) test

(cherry picked from commit 305f167889)

* Revert "Add debugging for TAB tests"

This reverts commit af393c1b0b.

Co-authored-by: Jeremy Apthorp <jeremya@chromium.org>
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-03-17 16:56:25 -04:00
Erick Zhao
d32e1f8d97 fix: prevent in-memory sessions from writing to custom spellchecker dictionary (#22157) (#22683)
* fix: prevent in-memory sessions from writing to custom dictionary

* docs

* spec
2020-03-17 10:50:00 -05:00
Shelley Vohr
b798e1ff54 fix: crash on invalid zoomFactor (#22708) 2020-03-17 10:43:06 -05:00
Electron Bot
bcb1d529ff Bump v9.0.0-beta.9 2020-03-16 08:31:53 -07:00
trop[bot]
e217a9416a fix: when building with enable_pepper_flash = false (#22692)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-03-15 11:59:34 -07:00
Erick Zhao
4be52b8f78 test: add specs for custom dictionary API (#22681) 2020-03-13 14:53:37 -04:00
Electron Bot
2bc7aaf2ef Bump v9.0.0-beta.8 2020-03-12 08:32:27 -07:00
Erick Zhao
1114954cbf fix: guard against duplicate TouchBarItem IDs (#22644) 2020-03-12 10:48:17 +09:00
trop[bot]
a76ea622b9 build: fix broken Views build (#22642)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-03-11 16:00:55 +09:00
trop[bot]
7ee7890fd8 test: test setPath for errors thrown (#22639)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-03-10 10:03:36 -07:00
trop[bot]
851ed7a6e7 fix: when building with enable_pdf_viewer = false (#22631)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-03-10 10:54:07 -04:00
loc
16c4d6e487 fix: port CL that fixes ARIA tree impl for macOS (#22421) 2020-03-10 19:53:39 +09:00
trop[bot]
56c0ba138b chore: don't delete nightly tag after draft (#22624)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-03-10 17:04:34 +09:00
Alexey Kuzmin
1883edd869 build: fix build without built-in spellchecker (#22610)
(cherry picked from commit 385d778a8b4e97c1cffa8f31efcf9748e82e3d94)
2020-03-10 16:59:39 +09:00
trop[bot]
9b5f2159a2 build: upload sentry src bundles to symbol S3 bucket (#22617)
Co-authored-by: Samuel Attard <sattard@slack-corp.com>
2020-03-09 16:24:44 -07:00
Samuel Maddock
60f16eaf95 fix: disallow loading extensions in temp sessions (#22090) (#22571)
Co-authored-by: Jeremy Apthorp <jeremya@chromium.org>
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-03-09 11:33:23 -07:00
Electron Bot
0f08c6c874 Bump v9.0.0-beta.7 2020-03-09 08:31:47 -07:00
trop[bot]
e227578ae0 optional typically sync callback for WebFrame#executeJavaScript* (#22501)
Co-authored-by: bughit <bughit@users.noreply.github.com>
2020-03-06 19:07:46 +09:00
trop[bot]
f413cda758 feat(extensions): add chrome.tabs.connect API (#22549)
* feat(extensions): add chrome.tabs.connect API

* test(extensions): verify that chrome.tabs.connect port communication works

Co-authored-by: samuelmaddock <samuel.maddock@gmail.com>
2020-03-06 19:06:40 +09:00
trop[bot]
c41b543842 feat: add events for spellcheck dictionary downloads (#22556)
Co-authored-by: Samuel Attard <sattard@slack-corp.com>
2020-03-06 19:04:52 +09:00
trop[bot]
7bb430dc44 docs: clean up dark mode related docs (#22562)
* docs: clean up systemPreferences.effectiveAppearance text

* Grammar fixes
* Add links for Electron Packager & Electron Forge
* Update Packager API links, given https://github.com/electron/electron-packager/pull/1131

* docs: clean up Dark Mode guide

* Grammar fixes
* Add links for Electron Packager & Electron Forge

* docs: adjust based on Electron 8 using 10.14 SDK

Co-authored-by: Mark Lee <electronjs@lazymalevolence.com>
2020-03-06 19:04:31 +09:00
Samuel Maddock
231f5af1a1 feat(extensions): add chrome.i18n API (#22570)
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
Co-authored-by: Samuel Maddock <samuel.maddock@gmail.com>

Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-03-06 19:03:38 +09:00
Samuel Attard
539ca773de feat: programmatically modify traffic light positioning (#22533) (#22566)
* setter

* getter

* specs and docs

* fixup

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

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-03-05 16:59:00 -08:00
Samuel Attard
1fc197bedb fix: allow persistent media salts (#22386) (#22567)
* fix: allow persistent media salts

* chore: add regression test for persistent media device ids across reloads

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-03-05 16:58:39 -08:00
Samuel Attard
926bea232d fix: reposition traffic lights on theme change (#22560)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-03-05 14:02:23 -08:00
Electron Bot
db664f3433 Bump v9.0.0-beta.6 2020-03-05 07:31:44 -08:00
Cheng Zhao
9ec73a3dcf fix: destroy node platform after destroying wrappers (#22535)
Co-authored-by: Cheng Zhao <zcbenz@electronjs.org>
2020-03-05 13:07:48 +09:00
Samuel Attard
c1c1ac2b2e fix: disable contextBridge object identity caching (#22525)
* fix: disable contextBridge object identity caching

* cleanup

* chore: make non-const references raw pointers

* fix: zero-param constructors are not explicit

* refactor: use base::LinkedList

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-03-04 16:54:05 -08:00
trop[bot]
9c931136d0 fix: do not reposition traffic lights when fullscreened (#22509)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-03-04 20:08:43 +09:00
trop[bot]
f01ee72ea5 fix: properly forward properties to webview (#22511)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-03-04 20:08:19 +09:00
trop[bot]
f6b4c39195 fix: bail early if no printers on the network (#22519)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-03-04 16:19:37 +09:00
Cheng Zhao
578f59532d chore: remove unneeded header (#22520) 2020-03-04 12:31:46 +09:00
trop[bot]
dcf9e4b2dd docs: add documentation on case insensitive dictionary hosting (#22487)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-03-03 14:30:30 -08:00
Shelley Vohr
2021f25453 chore: ensure correct scopes are in place (#22479) 2020-03-03 11:30:52 +09:00
John Kleinschmidt
faee8a092d fix: revive offscreen rendering support (#22160) (#22425)
(cherry picked from commit 36f982aee2)

Co-authored-by: Andy Dill <andy@discordapp.com>
2020-03-02 20:17:48 -05:00
Erick Zhao
3d65d84193 feat: add session.removeWordFromSpellCheckerDictionary API (#22368)
* feat: add session.removeWordFromSpellCheckerDictionary API

* rebase fixup
2020-03-02 14:46:19 -08:00
Jeremy Apthorp
5e05df9f71 chore: update chromium to 82.0.4058.2 (#22198)
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: loc <andy@slack-corp.com>
Co-authored-by: Robo <hop2deep@gmail.com>
2020-03-02 11:21:22 -08:00
Electron Bot
df2d03fe9b Bump v9.0.0-beta.5 2020-03-02 07:31:48 -08:00
trop[bot]
80967287ad fix: make webRequest work for CORS preflight requests (#22468)
* fix: support CORS preflight

* test: webRequest should work for CORS requests

Co-authored-by: Cheng Zhao <zcbenz@electronjs.org>
2020-03-02 20:25:28 +09:00
trop[bot]
2855f1d237 fix: do not call close on sheets themselves (#22445)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-03-02 16:50:22 +09:00
trop[bot]
5e25649e77 fix: Add ContentsView to AXChildren (#22469)
Co-authored-by: Felix Rieseberg <felix@felixrieseberg.com>
2020-03-02 16:28:38 +09:00
trop[bot]
3e90e523eb fix: add patch to set the base download URL rather than override it completely (#22385)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-02-28 17:00:44 -08:00
trop[bot]
c702aec1f8 fix: dictionaries download path should be in userdata (#22447)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-02-28 17:00:15 -08:00
Electron Bot
ede40f260e Bump v9.0.0-beta.4 2020-02-27 16:37:59 -08:00
Samuel Attard
ca53cc8380 fix: backport v8 patch for type inference issue (#22426) 2020-02-27 12:48:23 -08:00
Samuel Attard
7ec9b4e252 feat: set app.enableRendererProcessReuse to true by default (#22336) (#22401)
* feat: set app.enableRendererProcessReuse to true by default

* chore: add context aware info to breaking changes doc

* spec: fix nodeIntegration in child windows test for rendererprocessreuse

* spec: fix remote listeners in destroyed renderers spec as the error is now async

* Update api-browser-window-spec.ts

* chore: deprecate affinity

* chore: fix docs

* spec: handle tests crashing without an exist code

* spec: update tests for new rendererprocessreuse default

* spec: with renderer process re-use we get to destroy less views
2020-02-27 12:19:31 -08:00
trop[bot]
0d7e13d2a6 feat: add API for receiving logs from service workers (#22313)
* feat: add API for receiving logs from service workers

* feat: add new serviceWorkerContext APIs

* chore: add missing #include's

* refactor: rename serviceWorkerContext to serviceWorkers

* chore: clean up based on review

* chore: remove native_mate

* chore: add tests for the service worker module

* Update spec-main/api-service-workers-spec.ts

Co-Authored-By: Jeremy Apthorp <jeremya@chromium.org>

* chore: fix linting

* chore: handle renames

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-02-27 11:02:31 -08:00
Electron Bot
a5c56684b9 Revert "Bump v9.0.0-beta.4"
This reverts commit 68d96459c3.
2020-02-27 10:01:45 -08:00
Electron Bot
68d96459c3 Bump v9.0.0-beta.4 2020-02-27 09:14:14 -08:00
trop[bot]
6cf4757019 docs: improve documentation on spellchecker download URL (#22402)
* docs: improve documentation on spellchecker download URL

* Update session.md

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-02-26 23:09:43 -08:00
trop[bot]
6e80d6fba5 fix: pass safeDialogs preference properly (#22378)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-02-26 13:34:42 -08:00
trop[bot]
ec07954d5d test: disable clipboard tests for WOA (#22387)
Co-authored-by: Cheng Zhao <zcbenz@github.com>
2020-02-26 18:04:32 +09:00
Electron Bot
7fd2d39f72 Bump v9.0.0-beta.3 2020-02-25 14:03:20 -08:00
trop[bot]
64880c75a3 fix: emit will-navigate for sandboxed contents (#22327)
* fix: emit will-navigate for sandboxed contents

* uncomment test

* more tests

* use ShouldFork instead of browser_handles_all_top_level_requests

* forward post data in OpenURLFromTab

* align OpenURLFromTab with chrome's version (browser_navigator.cc/LoadURLInContents)

* add tests for navigating from file: and about:blank to http:

Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-02-25 11:11:33 +09:00
trop[bot]
cc94689db1 chore: allow custom node-spec-runner options (#22331)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-02-25 11:10:02 +09:00
trop[bot]
806e483049 fix(extensions): set lowest isolated world id (#22355)
* fix(extensions): set lowest isolated world id

* refactor: move world IDs into separate header file

Several files are including electron_render_frame_observer.h just for the world IDs.

Co-authored-by: Samuel Maddock <samuel.maddock@gmail.com>
2020-02-25 11:01:30 +09:00
Jeremy Apthorp
8129e92d2b refactor: saner blink_initialization_order.patch (#22054) (#22366) 2020-02-24 13:19:33 -08:00
trop[bot]
660706ba2c fix: disable remote layer APIs in MAS build (#22354)
* fix: add patch to disable remote layer APIs

* fix: use --disable-gpu-memory-buffer-compositor-resources for MAS build

Co-authored-by: Cheng Zhao <zcbenz@github.com>
2020-02-24 19:29:15 +09:00
trop[bot]
2feca9d35a fix: revert {Atom => Electron}Application rename (#22325)
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-02-24 12:29:10 +09:00
trop[bot]
3a4118703a docs: clean up protocol docs (#22308)
* docs: clean up protocol docs

* Fix capitalization

Co-authored-by: Mark Lee <malept@users.noreply.github.com>
2020-02-24 12:28:29 +09:00
Jeremy Apthorp
bd669f72ee feat: [extensions] support extension.getBackgroundPage (#21951) (#22177) 2020-02-21 14:33:28 -08:00
trop[bot]
1f3c3eee83 fix: typo in crash reporter constructor (#22322) 2020-02-21 17:50:32 +00:00
trop[bot]
6e84ebee8e chore: remove libcc from release not generator (#22294)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-02-20 10:17:41 -05:00
trop[bot]
f22376ef32 fix: add patch to route mouse event navigations through the WebContentsDelegate (#22204)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-02-19 13:46:15 +09:00
trop[bot]
324b49a5eb doc: remove accidental deprecation (#22264)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-02-19 13:44:45 +09:00
John Kleinschmidt
0e9727e8d5 ci: enable goma for all testing builds (#21992) (#22203)
(cherry picked from commit e7982623ec)
2020-02-18 12:03:33 -05:00
trop[bot]
44ee90e5cf fix: don't include breakpad_symbols dir in dsym.zip (#22221)
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-02-18 11:57:33 -05:00
Electron Bot
2b9ef75d82 Bump v9.0.0-beta.2 2020-02-15 16:07:17 -08:00
John Kleinschmidt
4dc2b4d55f Revert "Bump v9.0.0-beta.2"
This reverts commit 69f77d309d.
2020-02-14 16:50:33 -05:00
Electron Bot
69f77d309d Bump v9.0.0-beta.2 2020-02-14 12:39:21 -08:00
John Kleinschmidt
9cd1744a2b Revert "Bump v9.0.0-beta.2"
This reverts commit 8b11adc6f2.
2020-02-14 15:37:16 -05:00
trop[bot]
c6e411173e build: fix release script to work with sudowoodo (#22200)
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-02-14 15:35:10 -05:00
Electron Bot
8b11adc6f2 Bump v9.0.0-beta.2 2020-02-14 12:29:44 -08:00
trop[bot]
57ec30e459 feat: add session.listWordsFromSpellCheckerDictionary API (#22128)
* doesn't work yet but compiles.

* works

* fixup

Co-authored-by: Erick Zhao <erick@hotmail.ca>
2020-02-14 15:26:17 -05:00
trop[bot]
c4a836f95a fix: crash on custom printing margins (#22185)
Co-authored-by: Shelley Vohr <codebytere@github.com>
2020-02-14 15:40:01 +09:00
trop[bot]
9b2de2583e fix: no-arg console.log is undefined (#22171)
Co-authored-by: Shelley Vohr <codebytere@github.com>
2020-02-14 15:31:49 +09:00
Samuel Attard
7b2bfb4a0f chore: update NMV for Electron 9 (#22189) 2020-02-13 13:18:22 -08:00
Jeremy Apthorp
0e31826043 feat: enable pdf viewer 2020-02-13 10:09:29 -08:00
trop[bot]
7b3c073b3e fix RTL bug when used with traffic light repositioning (#22163)
Co-authored-by: tonyfwoo <55114329+tonyfwoo@users.noreply.github.com>
2020-02-12 11:29:03 -06:00
trop[bot]
2dc900b95d ci: Speed up release (#22159) 2020-02-12 07:27:21 +00:00
trop[bot]
f41423501a fix: make webRequest work with WebSocket (#22133)
* fix: web request support proxying websocket

* fix: make tests work

* chore: do not use api:: code outside api/ folder

* chore: do not create proxy when no listener

* test: use separate session to avoid conflicts

* chore: address review

Co-authored-by: Cheng Zhao <zcbenz@github.com>
2020-02-11 15:56:00 -05:00
trop[bot]
07d9728b63 build: fix spellchecker deps (#22155)
Co-authored-by: Alexey Kuzmin <alex.s.kuzmin@gmail.com>
2020-02-11 15:45:46 -05:00
trop[bot]
d4c90e80a5 refactor: use NSVisualEffectMaterial* constants directly (#22148) 2020-02-11 17:48:44 +00:00
trop[bot]
91141028e6 chore: print more logging for failed tests (#22116)
Co-authored-by: Cheng Zhao <zcbenz@github.com>
2020-02-11 15:07:54 +09:00
Electron Bot
9d69d4b9ef Bump v9.0.0-beta.1 2020-02-10 06:50:08 -08:00
Electron Bot
d57d5c544e Revert "Bump v9.0.0-beta.2"
This reverts commit 74d4dab157.
2020-02-10 06:38:44 -08:00
Electron Bot
74d4dab157 Bump v9.0.0-beta.2 2020-02-10 04:32:41 -08:00
trop[bot]
94246dabe3 ci: fix build failure on doc only changes (#22089)
* ci: fix build failure on doc only changes

* ci: fix doc-only check when CI fires on branch before PR is created

Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-02-10 17:09:35 +09:00
trop[bot]
4fe91e56ac chore: remove debugging log (#22095)
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-02-10 17:05:34 +09:00
trop[bot]
0d7440d676 build: preserve timestamps when stripping files (#22098)
* build: preserve timestamps when stripping files

Resolves an issue where the binaries in mksnapshot.zip were not getting stripped.

* Add missing comma

* Update script/strip-binaries.py

Co-Authored-By: Jeremy Apthorp <jeremya@chromium.org>

* Don't try to run strip on macOS

Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
2020-02-10 17:05:04 +09:00
trop[bot]
60edd2d3b1 build: try using newer version of xcode/macOS sdk (#22106)
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-02-10 16:48:51 +09:00
trop[bot]
d4d06660f3 fix: flash plugin (#22111)
* fix: flash plugin

Fixes https://github.com/electron/electron/issues/20744

* cleanup

* fix linting issue

Co-authored-by: t57ser <seve@live.at>
2020-02-10 10:50:56 +09:00
trop[bot]
8d8f15121b fix: use a WeakPtr so we do not UAF the store in FunctionLifetimeMonitor (#22113)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-02-10 10:47:23 +09:00
trop[bot]
1f8cb5144d build: copy chromedriver to correct location (#22092)
* build: copy chromedriver to correct location

* build: try to free up disk space for macos releases

* get verbose mode working on strip-binaries

* Only use separate chromedriver build arm/arm64

* fixup circleci config

Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-02-07 16:49:04 -05:00
trop[bot]
667ee359a1 test: get native unit tests running (#22086)
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-02-07 10:53:09 -05:00
trop[bot]
4b009159ba docs: clarify requirements for GOOGLE_API_KEY (#22071)
* docs: clarify requirements for GOOGLE_API_KEY

* Update docs/api/environment-variables.md

Co-Authored-By: Mark Lee <malept@users.noreply.github.com>

* Update docs/api/environment-variables.md

Co-Authored-By: Mark Lee <malept@users.noreply.github.com>

* Update docs/api/environment-variables.md

Co-Authored-By: Mark Lee <malept@users.noreply.github.com>

* update

Co-authored-by: Erick Zhao <erick@hotmail.ca>
Co-authored-by: Mark Lee <malept@users.noreply.github.com>
2020-02-06 15:25:28 -05:00
John Kleinschmidt
89f66bd00c Revert "Bump v9.0.0-beta.1"
This reverts commit 68346fec55.
2020-02-06 15:19:27 -05:00
trop[bot]
2d542c6028 build: copy chromedriver to proper directory for release (#22073)
Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-02-06 15:07:46 -05:00
Electron Bot
68346fec55 Bump v9.0.0-beta.1 2020-02-05 13:46:21 -08:00
Samuel Attard
23f32ca9f3 chore: prepare for 9.0.0-beta.1 2020-02-05 13:44:23 -08:00
675 changed files with 27507 additions and 24572 deletions

View File

@@ -227,7 +227,25 @@ step-gclient-sync: &step-gclient-sync
$GCLIENT_EXTRA_ARGS \
"$CIRCLE_REPOSITORY_URL"
gclient sync --with_branch_heads --with_tags
ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 gclient sync --with_branch_heads --with_tags
# Re-export all the patches to check if there were changes.
python src/electron/script/export_all_patches.py src/electron/patches/config.json
cd src/electron
git update-index --refresh || true
if ! git diff-index --quiet HEAD --; then
# There are changes to the patches. Make a git commit with the updated patches
git add patches
GIT_COMMITTER_NAME="Electron Bot" GIT_COMMITTER_EMAIL="anonymous@electronjs.org" git commit -m "update patches" --author="Electron Bot <anonymous@electronjs.org>"
# Export it
mkdir -p ../../patches
git format-patch -1 --stdout --keep-subject --no-stat --full-index > ../../patches/update-patches.patch
echo
echo "======================================================================"
echo "There were changes to the patches when applying."
echo "Check the CI artifacts for a patch you can apply to fix it."
echo "======================================================================"
exit 1
fi
fi
step-setup-env-for-build: &step-setup-env-for-build
@@ -342,7 +360,7 @@ step-install-signing-cert-on-mac: &step-install-signing-cert-on-mac
command: |
if [ "`uname`" == "Darwin" ]; then
cd src/electron
./script/codesign/import-testing-cert-ci.sh
./script/codesign/generate-identity.sh
fi
step-install-gnutar-on-mac: &step-install-gnutar-on-mac
@@ -681,6 +699,8 @@ step-maybe-generate-breakpad-symbols: &step-maybe-generate-breakpad-symbols
if [ "$GENERATE_SYMBOLS" == "true" ]; then
cd src
ninja -C out/Default electron:electron_symbols
cd out/Default/breakpad_symbols
find . -name \*.sym -print0 | xargs -0 npx @sentry/cli@1.51.1 difutil bundle-sources
fi
step-maybe-zip-symbols: &step-maybe-zip-symbols
@@ -970,6 +990,8 @@ steps-checkout-and-save-cache: &steps-checkout-and-save-cache
- *step-set-git-cache-path
# This sync call only runs if .circle-sync-done is an EMPTY file
- *step-gclient-sync
- store_artifacts:
path: patches
- *step-save-git-cache
# These next few steps reset Electron to the correct commit regardless of which cache was restored
- run:
@@ -988,6 +1010,7 @@ steps-checkout-and-save-cache: &steps-checkout-and-save-cache
sudo chown -R $(id -u):$(id -g) /portal
mv ./src /portal
- *step-save-src-cache
- *step-save-brew-cache
steps-electron-gn-check: &steps-electron-gn-check
steps:
@@ -1193,7 +1216,7 @@ steps-test-node: &steps-test-node
name: Run Node Tests
command: |
cd src
node electron/script/node-spec-runner.js junit
node electron/script/node-spec-runner.js --default --jUnitDir=junit
- store_test_results:
path: src/junit
@@ -1276,7 +1299,6 @@ commands:
at: .
- *step-restore-brew-cache
- *step-install-gnutar-on-mac
- *step-save-brew-cache
- when:
condition: << parameters.checkout-and-assume-cache >>
steps:
@@ -1302,6 +1324,8 @@ commands:
- *step-set-git-cache-path
# This sync call only runs if .circle-sync-done is an EMPTY file
- *step-gclient-sync
- store_artifacts:
path: patches
# These next few steps reset Electron to the correct commit regardless of which cache was restored
- when:
condition: << parameters.preserve-vendor-dirs >>
@@ -1672,7 +1696,6 @@ jobs:
<<: *machine-linux-2xlarge
environment:
<<: *env-linux-2xlarge-release
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
<<: *env-release-build
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
@@ -1685,6 +1708,7 @@ jobs:
<<: *machine-linux-2xlarge
environment:
<<: *env-linux-2xlarge-release
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
<<: *env-release-build
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
@@ -1734,7 +1758,6 @@ jobs:
<<: *machine-linux-2xlarge
environment:
<<: *env-linux-2xlarge-release
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
<<: *env-ia32
<<: *env-release-build
<<: *env-enable-sccache
@@ -1749,6 +1772,7 @@ jobs:
<<: *machine-linux-2xlarge
environment:
<<: *env-linux-2xlarge-release
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
<<: *env-ia32
<<: *env-release-build
<<: *env-enable-sccache
@@ -1805,7 +1829,6 @@ jobs:
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-32bit-release
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
@@ -1820,6 +1843,7 @@ jobs:
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-32bit-release
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
@@ -1879,7 +1903,6 @@ jobs:
<<: *env-arm64
<<: *env-release-build
<<: *env-enable-sccache
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm64=True --custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
@@ -1893,6 +1916,7 @@ jobs:
<<: *env-arm64
<<: *env-release-build
<<: *env-enable-sccache
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm64=True --custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
@@ -1949,7 +1973,6 @@ jobs:
<<: *env-mac-large-release
<<: *env-release-build
<<: *env-enable-sccache
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
@@ -1962,6 +1985,7 @@ jobs:
<<: *env-mac-large-release
<<: *env-release-build
<<: *env-enable-sccache
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
@@ -2022,7 +2046,6 @@ jobs:
<<: *env-mas
<<: *env-release-build
<<: *env-enable-sccache
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
@@ -2036,6 +2059,7 @@ jobs:
<<: *env-mas
<<: *env-release-build
<<: *env-enable-sccache
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:

View File

@@ -6,9 +6,11 @@
"browser": true
},
"rules": {
"semi": ["error", "always"],
"no-var": "error",
"no-unused-vars": 0,
"no-global-assign": 0,
"guard-for-in": 2,
"@typescript-eslint/no-unused-vars": ["error", {
"vars": "all",
"args": "after-used",

1
.gitattributes vendored
View File

@@ -1,3 +1,4 @@
# `git apply` and friends don't understand CRLF, even on windows. Force those
# files to be checked out with LF endings even if core.autocrlf is true.
*.patch text eol=lf
patches/**/.patches merge=union

12
.github/CODEOWNERS vendored
View File

@@ -3,10 +3,20 @@
# https://help.github.com/articles/about-codeowners
# https://git-scm.com/docs/gitignore
# Most stuff in here is owned by the Community & Safety WG...
/.github/* @electron/wg-community
# ...except the Admin WG maintains this file.
/.github/CODEOWNERS @electron/wg-admin
# Upgrades WG
/patches/ @electron/wg-upgrades
DEPS @electron/wg-upgrades
# Docs & Tooling WG
/default_app/ @electron/wg-docs-tools
/docs/ @electron/wg-docs-tools
# Releases WG
/npm/ @electron/wg-releases
/script/release @electron/wg-releases
/script/release @electron/wg-releases

View File

@@ -224,7 +224,6 @@ grit("resources") {
]
# Mojo manifest overlays are generated.
source_is_generated = true
grit_flags = [
"-E",
"target_gen_dir=" + rebase_path(target_gen_dir, root_build_dir),
@@ -500,9 +499,16 @@ source_set("electron_lib") {
"//third_party/breakpad:client",
"//ui/events/devices/x11",
"//ui/events/platform/x11",
"//ui/gtk",
"//ui/views/controls/webview",
"//ui/wm",
]
if (use_x11) {
deps += [
"//ui/gfx/x",
"//ui/gtk:x",
]
}
configs += [ ":gio_unix" ]
include_dirs += [ "//third_party/breakpad" ]
configs += [ "//build/config/linux:x11" ]
@@ -736,9 +742,14 @@ if (is_mac) {
sources = [
"$root_out_dir/egl_intermediates/libswiftshader_libEGL.dylib",
"$root_out_dir/egl_intermediates/libswiftshader_libGLESv2.dylib",
"$root_out_dir/vk_intermediates/libvk_swiftshader.dylib",
"$root_out_dir/vk_intermediates/vk_swiftshader_icd.json",
]
outputs = [ "{{bundle_contents_dir}}/Libraries/{{source_file_part}}" ]
public_deps = [ "//ui/gl:swiftshader_library_copy" ]
public_deps = [
"//ui/gl:swiftshader_egl_library_copy",
"//ui/gl:swiftshader_vk_library_copy",
]
}
}
group("electron_angle_library") {
@@ -791,6 +802,7 @@ if (is_mac) {
include_dirs = [ "." ]
sources = filenames.framework_sources
libs = []
if (enable_osr) {
libs += [ "IOSurface.framework" ]

6
DEPS
View File

@@ -12,9 +12,9 @@ gclient_gn_args = [
vars = {
'chromium_version':
'ddac4c3cc1528254008f9e7a2aea5d4426906bfd',
'83.0.4102.3',
'node_version':
'v12.15.0',
'v12.14.1',
'nan_version':
'2ee313aaca52e2b478965ac50eb5082520380d1b',
@@ -155,3 +155,5 @@ hooks = [
recursedeps = [
'src',
]
# Touch DEPS again to bust cache

View File

@@ -1 +1 @@
10.0.0-nightly.20200221
9.0.0-beta.15

View File

@@ -2,7 +2,7 @@ is_electron_build = true
root_extra_deps = [ "//electron" ]
# Registry of NMVs --> https://github.com/nodejs/node/blob/master/doc/abi_version_registry.json
node_module_version = 82
node_module_version = 80
v8_promise_internal_field_count = 1
v8_typed_array_max_size_in_heap = 0
@@ -21,7 +21,6 @@ dawn_enable_vulkan_validation_layers = false
is_cfi = false
# TODO: disabled due to crashes. re-enable.
enable_osr = false
enable_osr = true
enable_electron_extensions = true

View File

@@ -109,11 +109,15 @@ static_library("chrome") {
]
if (use_aura) {
sources += [
"//chrome/browser/platform_util_aura.cc",
"//chrome/browser/ui/views/color_chooser_aura.cc",
"//chrome/browser/ui/views/color_chooser_aura.h",
]
sources += [ "//chrome/browser/platform_util_aura.cc" ]
if (!is_win) {
sources += [
"//chrome/browser/ui/views/color_chooser_aura.cc",
"//chrome/browser/ui/views/color_chooser_aura.h",
]
}
deps += [ "//components/feature_engagement" ]
}
@@ -261,6 +265,7 @@ source_set("plugins") {
"//chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h",
]
deps += [
"//components/pdf/browser",
"//media:media_buildflags",
"//ppapi/buildflags",
"//ppapi/proxy:ipc",
@@ -298,8 +303,6 @@ source_set("plugins") {
sources += [
"//chrome/renderer/pepper/pepper_flash_drm_renderer_host.cc",
"//chrome/renderer/pepper/pepper_flash_drm_renderer_host.h",
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
"//chrome/renderer/pepper/pepper_flash_fullscreen_host.cc",
"//chrome/renderer/pepper/pepper_flash_fullscreen_host.h",
"//chrome/renderer/pepper/pepper_flash_menu_host.cc",
@@ -308,7 +311,14 @@ source_set("plugins") {
"//chrome/renderer/pepper/pepper_flash_renderer_host.h",
]
}
if (enable_pepper_flash || enable_pdf_viewer) {
sources += [
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
]
}
deps += [
"//components/pdf/renderer",
"//components/strings",
"//media:media_buildflags",
"//ppapi/host",

View File

@@ -1,48 +1,48 @@
import { app, dialog, BrowserWindow, shell, ipcMain } from 'electron'
import * as path from 'path'
import { app, dialog, BrowserWindow, shell, ipcMain } from 'electron';
import * as path from 'path';
let mainWindow: BrowserWindow | null = null
let mainWindow: BrowserWindow | null = null;
// Quit when all windows are closed.
app.on('window-all-closed', () => {
app.quit()
})
app.quit();
});
function decorateURL (url: string) {
// safely add `?utm_source=default_app
const parsedUrl = new URL(url)
parsedUrl.searchParams.append('utm_source', 'default_app')
return parsedUrl.toString()
const parsedUrl = new URL(url);
parsedUrl.searchParams.append('utm_source', 'default_app');
return parsedUrl.toString();
}
// Find the shortest path to the electron binary
const absoluteElectronPath = process.execPath
const relativeElectronPath = path.relative(process.cwd(), absoluteElectronPath)
const absoluteElectronPath = process.execPath;
const relativeElectronPath = path.relative(process.cwd(), absoluteElectronPath);
const electronPath = absoluteElectronPath.length < relativeElectronPath.length
? absoluteElectronPath
: relativeElectronPath
: relativeElectronPath;
const indexPath = path.resolve(app.getAppPath(), 'index.html')
const indexPath = path.resolve(app.getAppPath(), 'index.html');
function isTrustedSender (webContents: Electron.WebContents) {
if (webContents !== (mainWindow && mainWindow.webContents)) {
return false
return false;
}
const parsedUrl = new URL(webContents.getURL())
const parsedUrl = new URL(webContents.getURL());
const urlPath = process.platform === 'win32'
// Strip the prefixed "/" that occurs on windows
? path.resolve(parsedUrl.pathname.substr(1))
: parsedUrl.pathname
return parsedUrl.protocol === 'file:' && urlPath === indexPath
: parsedUrl.pathname;
return parsedUrl.protocol === 'file:' && urlPath === indexPath;
}
ipcMain.handle('bootstrap', (event) => {
return isTrustedSender(event.sender) ? electronPath : null
})
return isTrustedSender(event.sender) ? electronPath : null;
});
async function createWindow () {
await app.whenReady()
await app.whenReady();
const options: Electron.BrowserWindowConstructorOptions = {
width: 900,
@@ -57,46 +57,46 @@ async function createWindow () {
},
useContentSize: true,
show: false
}
};
if (process.platform === 'linux') {
options.icon = path.join(__dirname, 'icon.png')
options.icon = path.join(__dirname, 'icon.png');
}
mainWindow = new BrowserWindow(options)
mainWindow.on('ready-to-show', () => mainWindow!.show())
mainWindow = new BrowserWindow(options);
mainWindow.on('ready-to-show', () => mainWindow!.show());
mainWindow.webContents.on('new-window', (event, url) => {
event.preventDefault()
shell.openExternal(decorateURL(url))
})
event.preventDefault();
shell.openExternal(decorateURL(url));
});
mainWindow.webContents.session.setPermissionRequestHandler((webContents, permission, done) => {
const parsedUrl = new URL(webContents.getURL())
const parsedUrl = new URL(webContents.getURL());
const options: Electron.MessageBoxOptions = {
title: 'Permission Request',
message: `Allow '${parsedUrl.origin}' to access '${permission}'?`,
buttons: ['OK', 'Cancel'],
cancelId: 1
}
};
dialog.showMessageBox(mainWindow!, options).then(({ response }) => {
done(response === 0)
})
})
done(response === 0);
});
});
return mainWindow
return mainWindow;
}
export const loadURL = async (appUrl: string) => {
mainWindow = await createWindow()
mainWindow.loadURL(appUrl)
mainWindow.focus()
}
mainWindow = await createWindow();
mainWindow.loadURL(appUrl);
mainWindow.focus();
};
export const loadFile = async (appPath: string) => {
mainWindow = await createWindow()
mainWindow.loadFile(appPath)
mainWindow.focus()
}
mainWindow = await createWindow();
mainWindow.loadFile(appPath);
mainWindow.focus();
};

View File

@@ -1,8 +1,8 @@
import { app, dialog } from 'electron'
import { app, dialog } from 'electron';
import * as fs from 'fs'
import * as path from 'path'
import * as url from 'url'
import * as fs from 'fs';
import * as path from 'path';
import * as url from 'url';
type DefaultAppOptions = {
file: null | string;
@@ -14,10 +14,10 @@ type DefaultAppOptions = {
modules: string[];
}
const Module = require('module')
const Module = require('module');
// Parse command line options.
const argv = process.argv.slice(1)
const argv = process.argv.slice(1);
const option: DefaultAppOptions = {
file: null,
@@ -27,50 +27,50 @@ const option: DefaultAppOptions = {
interactive: false,
abi: false,
modules: []
}
};
let nextArgIsRequire = false
let nextArgIsRequire = false;
for (const arg of argv) {
if (nextArgIsRequire) {
option.modules.push(arg)
nextArgIsRequire = false
continue
option.modules.push(arg);
nextArgIsRequire = false;
continue;
} else if (arg === '--version' || arg === '-v') {
option.version = true
break
option.version = true;
break;
} else if (arg.match(/^--app=/)) {
option.file = arg.split('=')[1]
break
option.file = arg.split('=')[1];
break;
} else if (arg === '--interactive' || arg === '-i' || arg === '-repl') {
option.interactive = true
option.interactive = true;
} else if (arg === '--test-type=webdriver') {
option.webdriver = true
option.webdriver = true;
} else if (arg === '--require' || arg === '-r') {
nextArgIsRequire = true
continue
nextArgIsRequire = true;
continue;
} else if (arg === '--abi' || arg === '-a') {
option.abi = true
continue
option.abi = true;
continue;
} else if (arg === '--no-help') {
option.noHelp = true
continue
option.noHelp = true;
continue;
} else if (arg[0] === '-') {
continue
continue;
} else {
option.file = arg
break
option.file = arg;
break;
}
}
if (nextArgIsRequire) {
console.error('Invalid Usage: --require [file]\n\n"file" is required')
process.exit(1)
console.error('Invalid Usage: --require [file]\n\n"file" is required');
process.exit(1);
}
// Set up preload modules
if (option.modules.length > 0) {
Module._preloadModules(option.modules)
Module._preloadModules(option.modules);
}
function loadApplicationPackage (packagePath: string) {
@@ -79,102 +79,102 @@ function loadApplicationPackage (packagePath: string) {
configurable: false,
enumerable: true,
value: true
})
});
try {
// Override app name and version.
packagePath = path.resolve(packagePath)
const packageJsonPath = path.join(packagePath, 'package.json')
let appPath
packagePath = path.resolve(packagePath);
const packageJsonPath = path.join(packagePath, 'package.json');
let appPath;
if (fs.existsSync(packageJsonPath)) {
let packageJson
let packageJson;
try {
packageJson = require(packageJsonPath)
packageJson = require(packageJsonPath);
} catch (e) {
showErrorMessage(`Unable to parse ${packageJsonPath}\n\n${e.message}`)
return
showErrorMessage(`Unable to parse ${packageJsonPath}\n\n${e.message}`);
return;
}
if (packageJson.version) {
app.setVersion(packageJson.version)
app.setVersion(packageJson.version);
}
if (packageJson.productName) {
app.name = packageJson.productName
app.name = packageJson.productName;
} else if (packageJson.name) {
app.name = packageJson.name
app.name = packageJson.name;
}
appPath = packagePath
appPath = packagePath;
}
try {
const filePath = Module._resolveFilename(packagePath, module, true)
app._setDefaultAppPaths(appPath || path.dirname(filePath))
const filePath = Module._resolveFilename(packagePath, module, true);
app._setDefaultAppPaths(appPath || path.dirname(filePath));
} catch (e) {
showErrorMessage(`Unable to find Electron app at ${packagePath}\n\n${e.message}`)
return
showErrorMessage(`Unable to find Electron app at ${packagePath}\n\n${e.message}`);
return;
}
// Run the app.
Module._load(packagePath, module, true)
Module._load(packagePath, module, true);
} catch (e) {
console.error('App threw an error during load')
console.error(e.stack || e)
throw e
console.error('App threw an error during load');
console.error(e.stack || e);
throw e;
}
}
function showErrorMessage (message: string) {
app.focus()
dialog.showErrorBox('Error launching app', message)
process.exit(1)
app.focus();
dialog.showErrorBox('Error launching app', message);
process.exit(1);
}
async function loadApplicationByURL (appUrl: string) {
const { loadURL } = await import('./default_app')
loadURL(appUrl)
const { loadURL } = await import('./default_app');
loadURL(appUrl);
}
async function loadApplicationByFile (appPath: string) {
const { loadFile } = await import('./default_app')
loadFile(appPath)
const { loadFile } = await import('./default_app');
loadFile(appPath);
}
function startRepl () {
if (process.platform === 'win32') {
console.error('Electron REPL not currently supported on Windows')
process.exit(1)
console.error('Electron REPL not currently supported on Windows');
process.exit(1);
}
// prevent quitting
app.on('window-all-closed', () => {})
app.on('window-all-closed', () => {});
const repl = require('repl')
const repl = require('repl');
repl.start('> ').on('exit', () => {
process.exit(0)
})
process.exit(0);
});
}
// Start the specified app if there is one specified in command line, otherwise
// start the default app.
if (option.file && !option.webdriver) {
const file = option.file
const protocol = url.parse(file).protocol
const extension = path.extname(file)
const file = option.file;
const protocol = url.parse(file).protocol;
const extension = path.extname(file);
if (protocol === 'http:' || protocol === 'https:' || protocol === 'file:' || protocol === 'chrome:') {
loadApplicationByURL(file)
loadApplicationByURL(file);
} else if (extension === '.html' || extension === '.htm') {
loadApplicationByFile(path.resolve(file))
loadApplicationByFile(path.resolve(file));
} else {
loadApplicationPackage(file)
loadApplicationPackage(file);
}
} else if (option.version) {
console.log('v' + process.versions.electron)
process.exit(0)
console.log('v' + process.versions.electron);
process.exit(0);
} else if (option.abi) {
console.log(process.versions.modules)
process.exit(0)
console.log(process.versions.modules);
process.exit(0);
} else if (option.interactive) {
startRepl()
startRepl();
} else {
if (!option.noHelp) {
const welcomeMessage = `
@@ -192,10 +192,10 @@ Options:
-i, --interactive Open a REPL to the main process.
-r, --require Module to preload (option can be repeated).
-v, --version Print the version.
-a, --abi Print the Node ABI version.`
-a, --abi Print the Node ABI version.`;
console.log(welcomeMessage)
console.log(welcomeMessage);
}
loadApplicationByFile('index.html')
loadApplicationByFile('index.html');
}

View File

@@ -1,53 +1,53 @@
import { ipcRenderer, contextBridge } from 'electron'
import { ipcRenderer, contextBridge } from 'electron';
async function getOcticonSvg (name: string) {
try {
const response = await fetch(`octicon/${name}.svg`)
const div = document.createElement('div')
div.innerHTML = await response.text()
return div
const response = await fetch(`octicon/${name}.svg`);
const div = document.createElement('div');
div.innerHTML = await response.text();
return div;
} catch {
return null
return null;
}
}
async function loadSVG (element: HTMLSpanElement) {
for (const cssClass of element.classList) {
if (cssClass.startsWith('octicon-')) {
const icon = await getOcticonSvg(cssClass.substr(8))
const icon = await getOcticonSvg(cssClass.substr(8));
if (icon) {
for (const elemClass of element.classList) {
icon.classList.add(elemClass)
icon.classList.add(elemClass);
}
element.before(icon)
element.remove()
break
element.before(icon);
element.remove();
break;
}
}
}
}
async function initialize () {
const electronPath = await ipcRenderer.invoke('bootstrap')
const electronPath = await ipcRenderer.invoke('bootstrap');
function replaceText (selector: string, text: string) {
const element = document.querySelector<HTMLElement>(selector)
const element = document.querySelector<HTMLElement>(selector);
if (element) {
element.innerText = text
element.innerText = text;
}
}
replaceText('.electron-version', `Electron v${process.versions.electron}`)
replaceText('.chrome-version', `Chromium v${process.versions.chrome}`)
replaceText('.node-version', `Node v${process.versions.node}`)
replaceText('.v8-version', `v8 v${process.versions.v8}`)
replaceText('.command-example', `${electronPath} path-to-app`)
replaceText('.electron-version', `Electron v${process.versions.electron}`);
replaceText('.chrome-version', `Chromium v${process.versions.chrome}`);
replaceText('.node-version', `Node v${process.versions.node}`);
replaceText('.v8-version', `v8 v${process.versions.v8}`);
replaceText('.command-example', `${electronPath} path-to-app`);
for (const element of document.querySelectorAll<HTMLSpanElement>('.octicon')) {
loadSVG(element)
loadSVG(element);
}
}
contextBridge.exposeInMainWorld('electronDefaultApp', {
initialize
})
});

View File

@@ -112,7 +112,6 @@ These individual tutorials expand on topics discussed in the guide above.
* [Process Object](api/process.md)
* [Supported Command Line Switches](api/command-line-switches.md)
* [Environment Variables](api/environment-variables.md)
* [Chrome Extensions Support](api/extensions.md)
* [Breaking API Changes](breaking-changes.md)
### Custom DOM Elements:

View File

@@ -659,8 +659,6 @@ to the npm modules spec. You should usually also specify a `productName`
field, which is your application's full capitalized name, and which will be
preferred over `name` by Electron.
**[Deprecated](modernization/property-updates.md)**
### `app.setName(name)`
* `name` String
@@ -669,8 +667,6 @@ Overrides the current application's name.
**Note:** This function overrides the name used internally by Electron; it does not affect the name that the OS uses.
**[Deprecated](modernization/property-updates.md)**
### `app.getLocale()`
Returns `String` - The current application locale. Possible return values are documented [here](locales.md).
@@ -1089,14 +1085,10 @@ On macOS, it shows on the dock icon. On Linux, it only works for Unity launcher.
**Note:** Unity launcher requires the existence of a `.desktop` file to work,
for more information please read [Desktop Environment Integration][unity-requirement].
**[Deprecated](modernization/property-updates.md)**
### `app.getBadgeCount()` _Linux_ _macOS_
Returns `Integer` - The current value displayed in the counter badge.
**[Deprecated](modernization/property-updates.md)**
### `app.isUnityRunning()` _Linux_
Returns `Boolean` - Whether the current desktop environment is Unity launcher.
@@ -1171,8 +1163,6 @@ technologies, such as screen readers, has been detected. See
https://www.chromium.org/developers/design-documents/accessibility for more
details.
**[Deprecated](modernization/property-updates.md)**
### `app.setAccessibilitySupportEnabled(enabled)` _macOS_ _Windows_
* `enabled` Boolean - Enable or disable [accessibility tree](https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/the-accessibility-tree) rendering
@@ -1184,8 +1174,6 @@ This API must be called after the `ready` event is emitted.
**Note:** Rendering accessibility tree can significantly affect the performance of your app. It should not be enabled by default.
**[Deprecated](modernization/property-updates.md)**
### `app.showAboutPanel()`
Show the app's about panel options. These options can be overridden with `app.setAboutPanelOptions(options)`.

View File

@@ -289,7 +289,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
between the web pages even when you specified different values for them,
including but not limited to `preload`, `sandbox` and `nodeIntegration`.
So it is suggested to use exact same `webPreferences` for web pages with
the same `affinity`. _This property is experimental_
the same `affinity`. _Deprecated_
* `zoomFactor` Number (optional) - The default zoom factor of the page, `3.0` represents
`300%`. Default is `1.0`.
* `javascript` Boolean (optional) - Enables JavaScript support. Default is `true`.
@@ -369,6 +369,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
consecutive dialog protection is triggered. If not defined the default
message would be used, note that currently the default message is in
English and not localized.
* `disableDialogs` Boolean (optional) - Whether to disable dialogs
completely. Overrides `safeDialogs`. Default is `false`.
* `navigateOnDragDrop` Boolean (optional) - Whether dragging and dropping a
file or link onto the page causes a navigation. Default is `false`.
* `autoplayPolicy` String (optional) - Autoplay policy to apply to
@@ -1113,15 +1115,11 @@ Returns `Integer[]` - Contains the window's maximum width and height.
* `resizable` Boolean
Sets whether the window can be manually resized by user.
**[Deprecated](modernization/property-updates.md)**
Sets whether the window can be manually resized by the user.
#### `win.isResizable()`
Returns `Boolean` - Whether the window can be manually resized by user.
**[Deprecated](modernization/property-updates.md)**
Returns `Boolean` - Whether the window can be manually resized by the user.
#### `win.setMovable(movable)` _macOS_ _Windows_
@@ -1129,41 +1127,29 @@ Returns `Boolean` - Whether the window can be manually resized by user.
Sets whether the window can be moved by user. On Linux does nothing.
**[Deprecated](modernization/property-updates.md)**
#### `win.isMovable()` _macOS_ _Windows_
Returns `Boolean` - Whether the window can be moved by user.
On Linux always returns `true`.
**[Deprecated](modernization/property-updates.md)**
#### `win.setMinimizable(minimizable)` _macOS_ _Windows_
* `minimizable` Boolean
Sets whether the window can be manually minimized by user. On Linux does
nothing.
**[Deprecated](modernization/property-updates.md)**
Sets whether the window can be manually minimized by user. On Linux does nothing.
#### `win.isMinimizable()` _macOS_ _Windows_
Returns `Boolean` - Whether the window can be manually minimized by user
Returns `Boolean` - Whether the window can be manually minimized by the user.
On Linux always returns `true`.
**[Deprecated](modernization/property-updates.md)**
#### `win.setMaximizable(maximizable)` _macOS_ _Windows_
* `maximizable` Boolean
Sets whether the window can be manually maximized by user. On Linux does
nothing.
**[Deprecated](modernization/property-updates.md)**
Sets whether the window can be manually maximized by user. On Linux does nothing.
#### `win.isMaximizable()` _macOS_ _Windows_
@@ -1171,23 +1157,15 @@ Returns `Boolean` - Whether the window can be manually maximized by user.
On Linux always returns `true`.
**[Deprecated](modernization/property-updates.md)**
#### `win.setFullScreenable(fullscreenable)`
* `fullscreenable` Boolean
Sets whether the maximize/zoom window button toggles fullscreen mode or
maximizes the window.
**[Deprecated](modernization/property-updates.md)**
Sets whether the maximize/zoom window button toggles fullscreen mode or maximizes the window.
#### `win.isFullScreenable()`
Returns `Boolean` - Whether the maximize/zoom window button toggles fullscreen mode or
maximizes the window.
**[Deprecated](modernization/property-updates.md)**
Returns `Boolean` - Whether the maximize/zoom window button toggles fullscreen mode or maximizes the window.
#### `win.setClosable(closable)` _macOS_ _Windows_
@@ -1195,16 +1173,12 @@ maximizes the window.
Sets whether the window can be manually closed by user. On Linux does nothing.
**[Deprecated](modernization/property-updates.md)**
#### `win.isClosable()` _macOS_ _Windows_
Returns `Boolean` - Whether the window can be manually closed by user.
On Linux always returns `true`.
**[Deprecated](modernization/property-updates.md)**
#### `win.setAlwaysOnTop(flag[, level][, relativeLevel])`
* `flag` Boolean
@@ -1616,23 +1590,17 @@ This cannot be called when `titleBarStyle` is set to `customButtonsOnHover`.
Sets whether the window menu bar should hide itself automatically. Once set the
menu bar will only show when users press the single `Alt` key.
If the menu bar is already visible, calling `setAutoHideMenuBar(true)` won't
hide it immediately.
**[Deprecated](modernization/property-updates.md)**
If the menu bar is already visible, calling `setAutoHideMenuBar(true)` won't hide it immediately.
#### `win.isMenuBarAutoHide()`
Returns `Boolean` - Whether menu bar automatically hides itself.
**[Deprecated](modernization/property-updates.md)**
#### `win.setMenuBarVisibility(visible)` _Windows_ _Linux_
* `visible` Boolean
Sets whether the menu bar should be visible. If the menu bar is auto-hide, users
can still bring up the menu bar by pressing the single `Alt` key.
Sets whether the menu bar should be visible. If the menu bar is auto-hide, users can still bring up the menu bar by pressing the single `Alt` key.
#### `win.isMenuBarVisible()`
@@ -1748,6 +1716,17 @@ will remove the vibrancy effect on the window.
Note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` have been
deprecated and will be removed in an upcoming version of macOS.
#### `win.setTrafficLightPosition(position)` _macOS_
* `position` [Point](structures/point.md)
Set a custom position for the traffic light buttons. Can only be used with `titleBarStyle` set to `hidden`.
#### `win.getTrafficLightPosition()` _macOS_
Returns `Point` - The current position for the traffic light buttons. Can only be used with `titleBarStyle`
set to `hidden`.
#### `win.setTouchBar(touchBar)` _macOS_ _Experimental_
* `touchBar` TouchBar | null

View File

@@ -22,6 +22,9 @@ which the request is associated.
with which the request is associated. Defaults to the empty string. The
`session` option prevails on `partition`. Thus if a `session` is explicitly
specified, `partition` is ignored.
* `useSessionCookies` Boolean (optional) - Whether to send cookies with this
request from the provided session. This will make the `net` request's
cookie behavior match a `fetch` request. Default is `false`.
* `protocol` String (optional) - The protocol scheme in the form 'scheme:'.
Currently supported values are 'http:' or 'https:'. Defaults to 'http:'.
* `host` String (optional) - The server host provided as a concatenation of

View File

@@ -16,66 +16,80 @@ app.whenReady().then(() => {
})
```
## Electron CLI Flags
## --ignore-connections-limit=`domains`
### --auth-server-whitelist=`url`
Ignore the connections limit for `domains` list separated by `,`.
A comma-separated list of servers for which integrated authentication is enabled.
For example:
```sh
--auth-server-whitelist='*example.com, *foobar.com, *baz'
```
then any `url` ending with `example.com`, `foobar.com`, `baz` will be considered
for integrated authentication. Without `*` prefix the URL has to match exactly.
### --auth-negotiate-delegate-whitelist=`url`
A comma-separated list of servers for which delegation of user credentials is required.
Without `*` prefix the URL has to match exactly.
### --disable-http-cache
## --disable-http-cache
Disables the disk cache for HTTP requests.
### --disable-http2
## --disable-http2
Disable HTTP/2 and SPDY/3.1 protocols.
### --disable-renderer-backgrounding
## --lang
Prevents Chromium from lowering the priority of invisible pages' renderer
processes.
Set a custom locale.
This flag is global to all renderer processes, if you only want to disable
throttling in one window, you can take the hack of
[playing silent audio][play-silent-audio].
## --inspect=`port` and --inspect-brk=`port`
### --disk-cache-size=`size`
Debug-related flags, see the [Debugging the Main Process][debugging-main-process] guide for details.
## --remote-debugging-port=`port`
Enables remote debugging over HTTP on the specified `port`.
## --disk-cache-size=`size`
Forces the maximum disk space to be used by the disk cache, in bytes.
### --enable-api-filtering-logging
## --js-flags=`flags`
Enables caller stack logging for the following APIs (filtering events):
- `desktopCapturer.getSources()` / `desktop-capturer-get-sources`
- `remote.require()` / `remote-require`
- `remote.getGlobal()` / `remote-get-builtin`
- `remote.getBuiltin()` / `remote-get-global`
- `remote.getCurrentWindow()` / `remote-get-current-window`
- `remote.getCurrentWebContents()` / `remote-get-current-web-contents`
Specifies the flags passed to the Node.js engine. It has to be passed when starting
Electron if you want to enable the `flags` in the main process.
### --enable-logging
```sh
$ electron --js-flags="--harmony_proxies --harmony_collections" your-app
```
Prints Chromium's logging into console.
See the [Node.js documentation][node-cli] or run `node --help` in your terminal for a list of available flags. Additionally, run `node --v8-options` to see a list of flags that specifically refer to Node.js's V8 JavaScript engine.
This switch can not be used in `app.commandLine.appendSwitch` since it is parsed
earlier than user's app is loaded, but you can set the `ELECTRON_ENABLE_LOGGING`
environment variable to achieve the same effect.
## --proxy-server=`address:port`
### --host-rules=`rules`
Use a specified proxy server, which overrides the system setting. This switch
only affects requests with HTTP protocol, including HTTPS and WebSocket
requests. It is also noteworthy that not all proxy servers support HTTPS and
WebSocket requests. The proxy URL does not support username and password
authentication [per Chromium issue](https://bugs.chromium.org/p/chromium/issues/detail?id=615947).
## --proxy-bypass-list=`hosts`
Instructs Electron to bypass the proxy server for the given semi-colon-separated
list of hosts. This flag has an effect only if used in tandem with
`--proxy-server`.
For example:
```javascript
const { app } = require('electron')
app.commandLine.appendSwitch('proxy-bypass-list', '<local>;*.google.com;*foo.com;1.2.3.4:5678')
```
Will use the proxy server for all hosts except for local addresses (`localhost`,
`127.0.0.1` etc.), `google.com` subdomains, hosts that contain the suffix
`foo.com` and anything at `1.2.3.4:5678`.
## --proxy-pac-url=`url`
Uses the PAC script at the specified `url`.
## --no-proxy-server
Don't use a proxy server and always make direct connections. Overrides any other
proxy server flags that are passed.
## --host-rules=`rules`
A comma-separated list of `rules` that control how hostnames are mapped.
@@ -93,96 +107,69 @@ These mappings apply to the endpoint host in a net request (the TCP connect
and host resolver in a direct connection, and the `CONNECT` in an HTTP proxy
connection, and the endpoint host in a `SOCKS` proxy connection).
### --host-resolver-rules=`rules`
## --host-resolver-rules=`rules`
Like `--host-rules` but these `rules` only apply to the host resolver.
### --ignore-certificate-errors
## --auth-server-whitelist=`url`
Ignores certificate related errors.
### --ignore-connections-limit=`domains`
Ignore the connections limit for `domains` list separated by `,`.
### --js-flags=`flags`
Specifies the flags passed to the Node.js engine. It has to be passed when starting
Electron if you want to enable the `flags` in the main process.
```sh
$ electron --js-flags="--harmony_proxies --harmony_collections" your-app
```
See the [Node.js documentation][node-cli] or run `node --help` in your terminal for a list of available flags. Additionally, run `node --v8-options` to see a list of flags that specifically refer to Node.js's V8 JavaScript engine.
### --lang
Set a custom locale.
### --log-net-log=`path`
Enables net log events to be saved and writes them to `path`.
### --no-proxy-server
Don't use a proxy server and always make direct connections. Overrides any other
proxy server flags that are passed.
### --no-sandbox
Disables Chromium sandbox, which is now enabled by default.
Should only be used for testing.
### --proxy-bypass-list=`hosts`
Instructs Electron to bypass the proxy server for the given semi-colon-separated
list of hosts. This flag has an effect only if used in tandem with
`--proxy-server`.
A comma-separated list of servers for which integrated authentication is enabled.
For example:
```javascript
const { app } = require('electron')
app.commandLine.appendSwitch('proxy-bypass-list', '<local>;*.google.com;*foo.com;1.2.3.4:5678')
```sh
--auth-server-whitelist='*example.com, *foobar.com, *baz'
```
Will use the proxy server for all hosts except for local addresses (`localhost`,
`127.0.0.1` etc.), `google.com` subdomains, hosts that contain the suffix
`foo.com` and anything at `1.2.3.4:5678`.
then any `url` ending with `example.com`, `foobar.com`, `baz` will be considered
for integrated authentication. Without `*` prefix the URL has to match exactly.
### --proxy-pac-url=`url`
## --auth-negotiate-delegate-whitelist=`url`
Uses the PAC script at the specified `url`.
A comma-separated list of servers for which delegation of user credentials is required.
Without `*` prefix the URL has to match exactly.
### --proxy-server=`address:port`
## --ignore-certificate-errors
Use a specified proxy server, which overrides the system setting. This switch
only affects requests with HTTP protocol, including HTTPS and WebSocket
requests. It is also noteworthy that not all proxy servers support HTTPS and
WebSocket requests. The proxy URL does not support username and password
authentication [per Chromium issue](https://bugs.chromium.org/p/chromium/issues/detail?id=615947).
Ignores certificate related errors.
### --remote-debugging-port=`port`
Enables remote debugging over HTTP on the specified `port`.
### --ppapi-flash-path=`path`
## --ppapi-flash-path=`path`
Sets the `path` of the pepper flash plugin.
### --ppapi-flash-version=`version`
## --ppapi-flash-version=`version`
Sets the `version` of the pepper flash plugin.
### --v=`log_level`
## --log-net-log=`path`
Enables net log events to be saved and writes them to `path`.
## --disable-renderer-backgrounding
Prevents Chromium from lowering the priority of invisible pages' renderer
processes.
This flag is global to all renderer processes, if you only want to disable
throttling in one window, you can take the hack of
[playing silent audio][play-silent-audio].
## --enable-logging
Prints Chromium's logging into console.
This switch can not be used in `app.commandLine.appendSwitch` since it is parsed
earlier than user's app is loaded, but you can set the `ELECTRON_ENABLE_LOGGING`
environment variable to achieve the same effect.
## --v=`log_level`
Gives the default maximal active V-logging level; 0 is the default. Normally
positive values are used for V-logging levels.
This switch only works when `--enable-logging` is also passed.
### --vmodule=`pattern`
## --vmodule=`pattern`
Gives the per-module maximal V-logging levels to override the value given by
`--v`. E.g. `my_module=2,foo*=3` would change the logging level for all code in
@@ -194,38 +181,20 @@ logging level for all code in the source files under a `foo/bar` directory.
This switch only works when `--enable-logging` is also passed.
## Node.js Flags
## --enable-api-filtering-logging
Electron supports some of the [CLI flags][node-cli] supported by Node.js.
Enables caller stack logging for the following APIs (filtering events):
- `desktopCapturer.getSources()` / `desktop-capturer-get-sources`
- `remote.require()` / `remote-require`
- `remote.getGlobal()` / `remote-get-builtin`
- `remote.getBuiltin()` / `remote-get-global`
- `remote.getCurrentWindow()` / `remote-get-current-window`
- `remote.getCurrentWebContents()` / `remote-get-current-web-contents`
**Note:** Passing unsupported command line switches to Electron when it is not running in `ELECTRON_RUN_AS_NODE` will have no effect.
## --no-sandbox
### --inspect-brk[=[host:]port]
Activate inspector on host:port and break at start of user script. Default host:port is 127.0.0.1:9229.
Aliased to `--debug-brk=[host:]port`.
### --inspect-port=[host:]port
Set the `host:port` to be used when the inspector is activated. Useful when activating the inspector by sending the SIGUSR1 signal. Default host is `127.0.0.1`.
Aliased to `--debug-port=[host:]port`.
### --inspect[=[host:]port]
Activate inspector on `host:port`. Default is `127.0.0.1:9229`.
V8 inspector integration allows tools such as Chrome DevTools and IDEs to debug and profile Electron instances. The tools attach to Electron instances via a tcp port and communicate using the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/).
See the [Debugging the Main Process][debugging-main-process] guide for more details.
Aliased to `--debug[=[host:]port`.
### --inspect-publish-uid=stderr,http
Specify ways of the inspector web socket url exposure.
By default inspector websocket url is available in stderr and under /json/list endpoint on http://host:port/json/list.
Disables Chromium sandbox, which is now enabled by default.
Should only be used for testing.
[app]: app.md
[append-switch]: app.md#appcommandlineappendswitchswitch-value

View File

@@ -82,16 +82,12 @@ The API is only available in session's `will-download` callback function.
If user doesn't set the save path via the API, Electron will use the original
routine to determine the save path; this usually prompts a save dialog.
**[Deprecated](modernization/property-updates.md): use the `savePath` property instead.**
#### `downloadItem.getSavePath()`
Returns `String` - The save path of the download item. This will be either the path
set via `downloadItem.setSavePath(path)` or the path selected from the shown
save dialog.
**[Deprecated](modernization/property-updates.md): use the `savePath` property instead.**
#### `downloadItem.setSaveDialogOptions(options)`
* `options` SaveDialogOptions - Set the save file dialog options. This object has the same

View File

@@ -80,18 +80,6 @@ and spawned child processes that set `ELECTRON_RUN_AS_NODE`.
Starts the process as a normal Node.js process.
In this mode, you will be able to pass [cli options](https://nodejs.org/api/cli.html) to Node.js as
you would when running the normal Node.js executable, with the exception of the following flags:
* "--openssl-config"
* "--use-bundled-ca"
* "--use-openssl-ca",
* "--force-fips"
* "--enable-fips"
These flags are disabled owing to the fact that Electron uses BoringSSL instead of OpenSSL when building Node.js'
`crypto` module, and so will not work as designed.
### `ELECTRON_NO_ATTACH_CONSOLE` _Windows_
Don't attach to the current console session.

View File

@@ -1,104 +0,0 @@
# Chrome Extension Support
Electron supports a subset of the [Chrome Extensions
API][chrome-extensions-api-index], primarily to support DevTools extensions and
Chromium-internal extensions, but it also happens to support some other
extension capabilities.
[chrome-extensions-api-index]: https://developer.chrome.com/extensions/api_index
> **Note:** Electron does not support arbitrary Chrome extensions from the
> store, and it is a **non-goal** of the Electron project to be perfectly
> compatible with Chrome's implementation of Extensions.
## Loading extensions
Electron only supports loading unpacked extensions (i.e., `.crx` files do not
work). Extensions are installed per-`session`. To load an extension, call
[`ses.loadExtension`](session.md#sesloadextensionpath):
```js
const { session } = require('electron')
session.loadExtension('path/to/unpacked/extension').then(({ id }) => {
// ...
})
```
Loaded extensions will not be automatically remembered across exits; if you do
not call `loadExtension` when the app runs, the extension will not be loaded.
Note that loading extensions is only supported in persistent sessions.
Attempting to load an extension into an in-memory session will throw an error.
See the [`session`](session.md) documentation for more information about
loading, unloading, and querying active extensions.
## Supported Extensions APIs
We support the following extensions APIs, with some caveats. Other APIs may
additionally be supported, but support for any APIs not listed here is
provisional and may be removed.
### `chrome.devtools.inspectedWindow`
All features of this API are supported.
### `chrome.devtools.network`
All features of this API are supported.
### `chrome.devtools.panels`
All features of this API are supported.
### `chrome.extension`
The following properties of `chrome.extension` are supported:
- `chrome.extension.lastError`
The following methods of `chrome.extension` are supported:
- `chrome.extension.getURL`
- `chrome.extension.getBackgroundPage`
### `chrome.runtime`
The following properties of `chrome.runtime` are supported:
- `chrome.runtime.lastError`
- `chrome.runtime.id`
The following methods of `chrome.runtime` are supported:
- `chrome.runtime.getBackgroundPage`
- `chrome.runtime.getManifest`
- `chrome.runtime.getURL`
- `chrome.runtime.connect`
- `chrome.runtime.sendMessage`
The following events of `chrome.runtime` are supported:
- `chrome.runtime.onStartup`
- `chrome.runtime.onInstalled`
- `chrome.runtime.onSuspend`
- `chrome.runtime.onSuspendCanceled`
- `chrome.runtime.onConnect`
- `chrome.runtime.onMessage`
### `chrome.storage`
Only `chrome.storage.local` is supported; `chrome.storage.sync` and
`chrome.storage.managed` are not.
### `chrome.tabs`
The following methods of `chrome.tabs` are supported:
- `chrome.tabs.sendMessage`
- `chrome.tabs.executeScript`
> **Note:** In Chrome, passing `-1` as a tab ID signifies the "currently active
> tab". Since Electron has no such concept, passing `-1` as a tab ID is not
> supported and will raise an error.

View File

@@ -45,9 +45,3 @@ The Electron team is currently undergoing an initiative to convert separate gett
* `isMacTemplateImage`
* `SystemPreferences` module
* `appLevelAppearance`
* `webContents` module
* `audioMuted`
* `frameRate`
* `userAgent`
* `zoomFactor`
* `zoomLevel`

View File

@@ -276,14 +276,10 @@ Returns [`Size`](structures/size.md)
Marks the image as a template image.
**[Deprecated](modernization/property-updates.md)**
#### `image.isTemplateImage()`
Returns `Boolean` - Whether the image is a template image.
**[Deprecated](modernization/property-updates.md)**
#### `image.crop(rect)`
* `rect` [Rectangle](structures/rectangle.md) - The area of the image to crop.

View File

@@ -1,62 +1,62 @@
## Class: ServiceWorkers
> Query and receive events from a sessions active service workers.
Process: [Main](../glossary.md#main-process)
Instances of the `ServiceWorkers` class are accessed by using `serviceWorkers` property of
a `Session`.
For example:
```javascript
const { session } = require('electron')
// Get all service workers.
console.log(session.defaultSession.serviceWorkers.getAllRunning())
// Handle logs and get service worker info
session.defaultSession.serviceWorkers.on('console-message', (event, messageDetails) => {
console.log(
'Got service worker message',
messageDetails,
'from',
session.defaultSession.serviceWorkers.getFromVersionID(messageDetails.versionId)
)
})
```
### Instance Events
The following events are available on instances of `ServiceWorkers`:
#### Event: 'console-message'
Returns:
* `event` Event
* `messageDetails` Object - Information about the console message
* `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`.
* `sourceUrl` String - The URL the message came from
* `lineNumber` Number - The line number of the source that triggered this console message
Emitted when a service worker logs something to the console.
### Instance Methods
The following methods are available on instances of `ServiceWorkers`:
#### `serviceWorkers.getAllRunning()`
Returns `Record<Number, ServiceWorkerInfo>` - A [ServiceWorkerInfo](structures/service-worker-info.md) object where the keys are the service worker version ID and the values are the information about that service worker.
#### `serviceWorkers.getFromVersionID(versionId)`
* `versionId` Number
Returns [`ServiceWorkerInfo`](structures/service-worker-info.md) - Information about this service worker
If the service worker does not exist or is not running this method will throw an exception.
## Class: ServiceWorkers
> Query and receive events from a sessions active service workers.
Process: [Main](../glossary.md#main-process)
Instances of the `ServiceWorkers` class are accessed by using `serviceWorkers` property of
a `Session`.
For example:
```javascript
const { session } = require('electron')
// Get all service workers.
console.log(session.defaultSession.serviceWorkers.getAllRunning())
// Handle logs and get service worker info
session.defaultSession.serviceWorkers.on('console-message', (event, messageDetails) => {
console.log(
'Got service worker message',
messageDetails,
'from',
session.defaultSession.serviceWorkers.getFromVersionID(messageDetails.versionId)
)
})
```
### Instance Events
The following events are available on instances of `ServiceWorkers`:
#### Event: 'console-message'
Returns:
* `event` Event
* `messageDetails` Object - Information about the console message
* `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`.
* `sourceUrl` String - The URL the message came from
* `lineNumber` Number - The line number of the source that triggered this console message
Emitted when a service worker logs something to the console.
### Instance Methods
The following methods are available on instances of `ServiceWorkers`:
#### `serviceWorkers.getAllRunning()`
Returns `Record<Number, ServiceWorkerInfo>` - A [ServiceWorkerInfo](structures/service-worker-info.md) object where the keys are the service worker version ID and the values are the information about that service worker.
#### `serviceWorkers.getFromVersionID(versionId)`
* `versionId` Number
Returns [`ServiceWorkerInfo`](structures/service-worker-info.md) - Information about this service worker
If the service worker does not exist or is not running this method will throw an exception.

View File

@@ -105,6 +105,45 @@ Returns:
Emitted when a render process requests preconnection to a URL, generally due to
a [resource hint](https://w3c.github.io/resource-hints/).
#### Event: 'spellcheck-dictionary-initialized'
Returns:
* `event` Event
* `languageCode` String - The language code of the dictionary file
Emitted when a hunspell dictionary file has been successfully initialized. This
occurs after the file has been downloaded.
#### Event: 'spellcheck-dictionary-download-begin'
Returns:
* `event` Event
* `languageCode` String - The language code of the dictionary file
Emitted when a hunspell dictionary file starts downloading
#### Event: 'spellcheck-dictionary-download-success'
Returns:
* `event` Event
* `languageCode` String - The language code of the dictionary file
Emitted when a hunspell dictionary file has been successfully downloaded
#### Event: 'spellcheck-dictionary-download-failure'
Returns:
* `event` Event
* `languageCode` String - The language code of the dictionary file
Emitted when a hunspell dictionary file download fails. For details
on the failure you should collect a netlog and inspect the download
request.
### Instance Methods
The following methods are available on instances of `Session`:
@@ -483,7 +522,12 @@ setting with the current OS locale. This setting is persisted across restarts.
By default Electron will download hunspell dictionaries from the Chromium CDN. If you want to override this
behavior you can use this API to point the dictionary downloader at your own hosted version of the hunspell
dictionaries. We publish a `hunspell_dictionaries.zip` file with each release which contains the files you need
to host here.
to host here, the file server must be **case insensitive** you must upload each file twice, once with the case it
has in the ZIP file and once with the filename as all lower case.
If the files present in `hunspell_dictionaries.zip` are available at `https://example.com/dictionaries/language-code.bdic`
then you should call this api with `ses.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')`. Please
note the trailing slash. The URL to the dictionaries is formed as `${url}${filename}`.
**Note:** On macOS the OS spellchecker is used and therefore we do not download any dictionary files. This API is a no-op on macOS.
@@ -496,7 +540,8 @@ Resolves when the full dictionary is loaded from disk.
* `word` String - The word you want to add to the dictionary
Returns `Boolean` - Whether the word was successfully written to the custom dictionary.
Returns `Boolean` - Whether the word was successfully written to the custom dictionary. This API
will not work on non-persistent (in-memory) sessions.
**Note:** On macOS and Windows 10 this word will be written to the OS custom dictionary as well
@@ -504,7 +549,8 @@ Returns `Boolean` - Whether the word was successfully written to the custom dict
* `word` String - The word you want to remove from the dictionary
Returns `Boolean` - Whether the word was successfully removed from the custom dictionary.
Returns `Boolean` - Whether the word was successfully removed from the custom dictionary. This API
will not work on non-persistent (in-memory) sessions.
**Note:** On macOS and Windows 10 this word will be removed from the OS custom dictionary as well
@@ -520,8 +566,6 @@ requests an API that Electron does not support) then they will be logged to the
console.
Note that Electron does not support the full range of Chrome extensions APIs.
See [Supported Extensions APIs](extensions.md#supported-extensions-apis) for
more details on what is supported.
Note that in previous versions of Electron, extensions that were loaded would
be remembered for future runs of the application. This is no longer the case:
@@ -544,9 +588,6 @@ This API does not support loading packed (.crx) extensions.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
**Note:** Loading extensions into in-memory (non-persistent) sessions is not
supported and will throw an error.
#### `ses.removeExtension(extensionId)`
* `extensionId` String - ID of extension to remove

View File

@@ -1,5 +1,8 @@
# Extension Object
* `id` String
* `manifest` any - Copy of the [extension's manifest data](https://developer.chrome.com/extensions/manifest).
* `name` String
* `path` String - The extension's file path.
* `version` String
* `url` String - The extension's `chrome-extension://` URL.

View File

@@ -360,7 +360,7 @@ Returns `Boolean` - `true` if an inverted color scheme (a high contrast color sc
Returns `Boolean` - `true` if a high contrast theme is active, `false` otherwise.
**Depreacted:** Should use the new [`nativeTheme.shouldUseHighContrastColors`](native-theme.md#nativethemeshouldusehighcontrastcolors-macos-windows-readonly) API.
**Deprecated:** Should use the new [`nativeTheme.shouldUseHighContrastColors`](native-theme.md#nativethemeshouldusehighcontrastcolors-macos-windows-readonly) API.
### `systemPreferences.getEffectiveAppearance()` _macOS_
@@ -369,16 +369,6 @@ Returns `String` - Can be `dark`, `light` or `unknown`.
Gets the macOS appearance setting that is currently applied to your application,
maps to [NSApplication.effectiveAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)
Please note that until Electron is built targeting the 10.14 SDK, your application's
`effectiveAppearance` will default to 'light' and won't inherit the OS preference. In
the interim in order for your application to inherit the OS preference you must set the
`NSRequiresAquaSystemAppearance` key in your apps `Info.plist` to `false`. If you are
using `electron-packager` or `electron-forge` just set the `enableDarwinDarkMode`
packager option to `true`. See the [Electron Packager API](https://github.com/electron/electron-packager/blob/master/docs/api.md#darwindarkmodesupport)
for more details.
**[Deprecated](modernization/property-updates.md)**
### `systemPreferences.getAppLevelAppearance()` _macOS_ _Deprecated_
Returns `String` | `null` - Can be `dark`, `light` or `unknown`.
@@ -387,8 +377,6 @@ Gets the macOS appearance setting that you have declared you want for
your application, maps to [NSApplication.appearance](https://developer.apple.com/documentation/appkit/nsapplication/2967170-appearance?language=objc).
You can use the `setAppLevelAppearance` API to set this value.
**[Deprecated](modernization/property-updates.md)**
### `systemPreferences.setAppLevelAppearance(appearance)` _macOS_ _Deprecated_
* `appearance` String | null - Can be `dark` or `light`
@@ -396,8 +384,6 @@ You can use the `setAppLevelAppearance` API to set this value.
Sets the appearance setting for your application, this should override the
system default and override the value of `getEffectiveAppearance`.
**[Deprecated](modernization/property-updates.md)**
### `systemPreferences.canPromptTouchID()` _macOS_
Returns `Boolean` - whether or not this device has the ability to use Touch ID.
@@ -478,11 +464,3 @@ A `String` property that can be `dark`, `light` or `unknown`.
Returns the macOS appearance setting that is currently applied to your application,
maps to [NSApplication.effectiveAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)
Please note that until Electron is built targeting the 10.14 SDK, your application's
`effectiveAppearance` will default to 'light' and won't inherit the OS preference. In
the interim in order for your application to inherit the OS preference you must set the
`NSRequiresAquaSystemAppearance` key in your apps `Info.plist` to `false`. If you are
using `electron-packager` or `electron-forge` just set the `enableDarwinDarkMode`
packager option to `true`. See the [Electron Packager API](https://github.com/electron/electron-packager/blob/master/docs/api.md#darwindarkmodesupport)
for more details.

View File

@@ -310,7 +310,7 @@ and allow the page to be unloaded.
const { BrowserWindow, dialog } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600 })
win.webContents.on('will-prevent-unload', (event) => {
const choice = dialog.showMessageBoxSync(win, {
const choice = dialog.showMessageBox(win, {
type: 'question',
buttons: ['Leave', 'Stay'],
title: 'Do you want to leave this site?',
@@ -967,14 +967,10 @@ Returns `Boolean` - Whether the renderer process has crashed.
Overrides the user agent for this web page.
**[Deprecated](modernization/property-updates.md)**
#### `contents.getUserAgent()`
Returns `String` - The user agent for this web page.
**[Deprecated](modernization/property-updates.md)**
#### `contents.insertCSS(css[, options])`
* `css` String
@@ -1054,33 +1050,27 @@ Ignore application menu shortcuts while this web contents is focused.
Mute the audio on the current web page.
**[Deprecated](modernization/property-updates.md)**
#### `contents.isAudioMuted()`
Returns `Boolean` - Whether this page has been muted.
**[Deprecated](modernization/property-updates.md)**
#### `contents.isCurrentlyAudible()`
Returns `Boolean` - Whether audio is currently playing.
#### `contents.setZoomFactor(factor)`
* `factor` Number - Zoom factor.
* `factor` Double - Zoom factor; default is 1.0.
Changes the zoom factor to the specified factor. Zoom factor is
zoom percent divided by 100, so 300% = 3.0.
**[Deprecated](modernization/property-updates.md)**
The factor must be greater than 0.0.
#### `contents.getZoomFactor()`
Returns `Number` - the current zoom factor.
**[Deprecated](modernization/property-updates.md)**
#### `contents.setZoomLevel(level)`
* `level` Number - Zoom level.
@@ -1090,14 +1080,10 @@ increment above or below represents zooming 20% larger or smaller to default
limits of 300% and 50% of original size, respectively. The formula for this is
`scale := 1.2 ^ level`.
**[Deprecated](modernization/property-updates.md)**
#### `contents.getZoomLevel()`
Returns `Number` - the current zoom level.
**[Deprecated](modernization/property-updates.md)**
#### `contents.setVisualZoomLevelLimits(minimumLevel, maximumLevel)`
* `minimumLevel` Number
@@ -1286,7 +1272,7 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`.
* `callback` Function (optional)
* `success` Boolean - Indicates success of the print call.
* `failureReason` String - Called back if the print fails; can be `cancelled` or `failed`.
* `failureReason` String - Error description called back if the print fails.
Prints window's web page. When `silent` is set to `true`, Electron will pick
the system's default printer if `deviceName` is empty and the default settings for printing.
@@ -1709,14 +1695,10 @@ Returns `Boolean` - If *offscreen rendering* is enabled returns whether it is cu
If *offscreen rendering* is enabled sets the frame rate to the specified number.
Only values between 1 and 60 are accepted.
**[Deprecated](modernization/property-updates.md)**
#### `contents.getFrameRate()`
Returns `Integer` - If *offscreen rendering* is enabled returns the current frame rate.
**[Deprecated](modernization/property-updates.md)**
#### `contents.invalidate()`
Schedules a full repaint of the window this web contents is in.

View File

@@ -22,11 +22,13 @@ The `WebFrame` class has the following instance methods:
### `webFrame.setZoomFactor(factor)`
* `factor` Number - Zoom factor.
* `factor` Double - Zoom factor; default is 1.0.
Changes the zoom factor to the specified factor. Zoom factor is
zoom percent divided by 100, so 300% = 3.0.
The factor must be greater than 0.0.
### `webFrame.getZoomFactor()`
Returns `Number` - The current zoom factor.
@@ -122,13 +124,20 @@ by its key, which is returned from `webFrame.insertCSS(css)`.
Inserts `text` to the focused element.
### `webFrame.executeJavaScript(code[, userGesture])`
### `webFrame.executeJavaScript(code[, userGesture, callback])`
* `code` String
* `userGesture` Boolean (optional) - Default is `false`.
* `callback` Function (optional) - Called after script has been executed. Unless
the frame is suspended (e.g. showing a modal alert), execution will be
synchronous and the callback will be invoked before the method returns. For
compatibility with an older version of this method, the error parameter is
second.
* `result` Any
* `error` Error
Returns `Promise<any>` - A promise that resolves with the result of the executed code
or is rejected if the result of the code is a rejected promise.
Returns `Promise<any>` - A promise that resolves with the result of the executed
code or is rejected if execution throws or results in a rejected promise.
Evaluates `code` in page.
@@ -136,14 +145,24 @@ In the browser window some HTML APIs like `requestFullScreen` can only be
invoked by a gesture from the user. Setting `userGesture` to `true` will remove
this limitation.
### `webFrame.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture])`
### `webFrame.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture, callback])`
* `worldId` Integer - The ID of the world to run the javascript in, `0` is the default world, `999` is the world used by Electrons `contextIsolation` feature. You can provide any integer here.
* `worldId` Integer - The ID of the world to run the javascript
in, `0` is the default main world (where content runs), `999` is the
world used by Electron's `contextIsolation` feature. Accepts values
in the range 1..536870911.
* `scripts` [WebSource[]](structures/web-source.md)
* `userGesture` Boolean (optional) - Default is `false`.
* `callback` Function (optional) - Called after script has been executed. Unless
the frame is suspended (e.g. showing a modal alert), execution will be
synchronous and the callback will be invoked before the method returns. For
compatibility with an older version of this method, the error parameter is
second.
* `result` Any
* `error` Error
Returns `Promise<any>` - A promise that resolves with the result of the executed code
or is rejected if the result of the code is a rejected promise.
Returns `Promise<any>` - A promise that resolves with the result of the executed
code or is rejected if execution throws or results in a rejected promise.
Works like `executeJavaScript` but evaluates `scripts` in an isolated context.

View File

@@ -6,26 +6,6 @@ Breaking changes will be documented here, and deprecation warnings added to JS c
The `FIXME` string is used in code comments to denote things that should be fixed for future releases. See https://github.com/electron/electron/search?q=fixme
## Planned Breaking API Changes (10.0)
### `enableRemoteModule` defaults to `false`
In Electron 9, using the remote module without explicitly enabling it via the
`enableRemoteModule` WebPreferences option began emitting a warning. In
Electron 10, the remote module is now disabled by default. To use the remote
module, `enableRemoteModule: true` must be specified in WebPreferences:
```js
const w = new BrowserWindow({
webPreferences: {
enableRemoteModule: true
}
})
```
We [recommend moving away from the remote
module](https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31).
## Planned Breaking API Changes (9.0)
### `<webview>.getWebContents()`

View File

@@ -48,7 +48,7 @@ still set breakpoints - Visual Studio will automatically figure out that the
source code matches the code running in the attached process and break
accordingly.
Relevant code files can be found in `./shell/`.
Relevant code files can be found in `./atom/`.
### Attaching

View File

@@ -46,7 +46,7 @@ this basic introduction, let's assume that you're calling a command from JavaScr
that isn't behaving correctly - so you'd like to break on that command's C++
counterpart inside the Electron source.
Relevant code files can be found in `./shell/`.
Relevant code files can be found in `./atom/`.
Let's assume that you want to debug `app.setName()`, which is defined in `browser.cc`
as `Browser::SetName()`. Set the breakpoint using the `breakpoint` command, specifying

View File

@@ -55,7 +55,7 @@ $ git checkout -b my-branch -t upstream/master
### Step 4: Code
Most pull requests opened against the `electron/electron` repository include
changes to either the C/C++ code in the `shell/` folder,
changes to either the C/C++ code in the `atom/` folder,
the JavaScript code in the `lib/` folder, the documentation in `docs/api/`
or tests in the `spec/` folder.

View File

@@ -21,7 +21,7 @@
<p>
Open the
<a href="https://electronjs.org/docs/api/menu"
<a href="http://electron.atom.io/docs/api/menu"
>full API documentation<span
>(opens in new window)</span
></a
@@ -111,7 +111,7 @@
<p>
See the full
<a
href="https://electronjs.org/docs/api/web-contents/#event-context-menu"
href="http://electron.atom.io/docs/api/web-contents/#event-context-menu"
>context-menu event documentation</a
>
for all the available properties.

View File

@@ -159,7 +159,7 @@ const template = [
{
label: 'Learn More',
click: () => {
shell.openExternal('https://electronjs.org')
shell.openExternal('http://electron.atom.io')
}
}
]

View File

@@ -21,10 +21,10 @@
<p>
Open the full documentation for the
<a href="https://electronjs.org/docs/api/menu">Menu</a>,
<a href="https://electronjs.org/docs/api/accelerator">Accelerator</a>,
<a href="http://electron.atom.io/docs/api/menu">Menu</a>,
<a href="http://electron.atom.io/docs/api/accelerator">Accelerator</a>,
and
<a href="https://electronjs.org/docs/api/global-shortcut">globalShortcut</a>
<a href="http://electron.atom.io/docs/api/global-shortcut">globalShortcut</a>
APIs in your browser.
</p>

View File

@@ -23,7 +23,7 @@
<p>
Open the
<a href="https://electronjs.org/docs/api/dialog/">
<a href="http://electron.atom.io/docs/api/dialog/">
full API documentation (opens in new window)
</a>
in your browser.

View File

@@ -23,7 +23,7 @@
<p>
Open the
<a href="https://electronjs.org/docs/api/dialog/">
<a href="http://electron.atom.io/docs/api/dialog/">
full API documentation (opens in new window)
</a>
in your browser.

View File

@@ -23,7 +23,7 @@
<p>
Open the
<a href="https://electronjs.org/docs/api/dialog/">
<a href="http://electron.atom.io/docs/api/dialog/">
full API documentation (opens in new window)
</a>
in your browser.

View File

@@ -23,7 +23,7 @@
<p>
Open the
<a href="https://electronjs.org/docs/api/dialog/">
<a href="http://electron.atom.io/docs/api/dialog/">
full API documentation (opens in new window)
</a>
in your browser.

View File

@@ -27,7 +27,7 @@
const { shell } = require('electron')
const exLinksBtn = document.getElementById('open-ex-links')
exLinksBtn.addEventListener('click', (event) => {
shell.openExternal('https://electronjs.org')
shell.openExternal('http://electron.atom.io')
})
</code></pre>

View File

@@ -3,7 +3,7 @@ const { shell } = require('electron')
const exLinksBtn = document.getElementById('open-ex-links')
exLinksBtn.addEventListener('click', (event) => {
shell.openExternal('https://electronjs.org')
shell.openExternal('http://electron.atom.io')
})
const OpenAllOutboundLinks = () => {

View File

@@ -17,7 +17,7 @@
<p>This module works in both the main and renderer process.</p>
<p>
Open the
<a href="https://electronjs.org/docs/api/shell">
<a href="http://electron.atom.io/docs/api/shell">
full API documentation (opens in new window)
</a>
in your browser.

View File

@@ -9,5 +9,5 @@ fileManagerBtn.addEventListener('click', (event) => {
})
exLinksBtn.addEventListener('click', (event) => {
shell.openExternal('https://electronjs.org')
shell.openExternal('http://electron.atom.io')
})

View File

@@ -26,7 +26,7 @@
<p>
Open the
<a href="https://electronjs.org/docs/all/#notifications-windows-linux-macos">
<a href="https://electron.atom.io/docs/all/#notifications-windows-linux-macos">
full API documentation<span>(opens in new window)</span>
</a>
in your browser.

View File

@@ -15,7 +15,7 @@
<p>
Open the
<a href="https://electronjs.org/docs/api/tray">
<a href="http://electron.atom.io/docs/api/tray">
full API documentation (opens in new window)
</a>
in your browser.
@@ -108,7 +108,7 @@ ipc.on('tray-removed', function () {
On Linux distributions that only have app indicator support, users
will need to install <code>libappindicator1</code> to make the
tray icon work. See the
<a href="https://electronjs.org/docs/api/tray">
<a href="http://electron.atom.io/docs/api/tray">
full API documentation (opens in new window)
</a>
for more details about using Tray on Linux.

View File

@@ -13,7 +13,7 @@
<h3>The <code>app</code> module provides methods for handling protocols.</h3>
<p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a browser asks to be your default for viewing web pages.</p>
<p>Open the <a href="https://electronjs.org/docs/api/app">full app API documentation<span class="u-visible-to-screen-reader">(opens in new window)</span></a> in your browser.</p>
<p>Open the <a href="http://electron.atom.io/docs/api/app">full app API documentation<span class="u-visible-to-screen-reader">(opens in new window)</span></a> in your browser.</p>
</header>
<div >
@@ -89,4 +89,4 @@
</html>
</body>
</html>
</html>

View File

@@ -15,7 +15,7 @@
</div>
<p>The <code>process</code> module is built into Node.js (therefore you can use this in both the main and renderer processes) and in Electron apps this object has a few more useful properties on it.</p>
<p>The example below gets the version of Electron in use by the app.</p>
<p>See the <a href="https://electronjs.org/docs/api/process">process documentation <span>(opens in new window)</span></a> for more.</p>
<p>See the <a href="http://electron.atom.io/docs/api/process">process documentation <span>(opens in new window)</span></a> for more.</p>
</div>
</div>
</div>

View File

@@ -22,7 +22,7 @@
<p>
Open the
<a href="https://electronjs.org/docs/api/browser-window">
<a href="http://electron.atom.io/docs/api/browser-window">
full API documentation (opens in new window)
</a>
in your browser.
@@ -59,7 +59,7 @@
<p>
For more details, see the
<a href="https://electronjs.org/docs/api/frameless-window/">
<a href="http://electron.atom.io/docs/api/frameless-window/">
Frameless Window
</a>
documentation.

View File

@@ -22,7 +22,7 @@
<p>
Open the
<a href="https://electronjs.org/docs/api/browser-window">
<a href="http://electron.atom.io/docs/api/browser-window">
full API documentation (opens in new window)
</a>
in your browser.
@@ -47,7 +47,7 @@
There are a lot of methods for controlling the state of the window
such as the size, location, and focus status as well as events to
listen to for window changes. Visit the
<a href="https://electronjs.org/docs/api/browser-window">
<a href="http://electron.atom.io/docs/api/browser-window">
documentation (opens in new window)
</a>
for the full list.

View File

@@ -15,5 +15,5 @@ newWindowBtn.addEventListener('click', (event) => {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal("https://electronjs.org/docs/api/browser-window")
shell.openExternal("http://electron.atom.io/docs/api/browser-window")
})

View File

@@ -22,7 +22,7 @@
<p>
Open the
<a href="https://electronjs.org/docs/api/browser-window">
<a href="http://electron.atom.io/docs/api/browser-window">
full API documentation (opens in new window)
</a>
in your browser.

View File

@@ -14,5 +14,5 @@
| 6.0.0 | 2019-05-01 | 2019-07-30 | M76 | v12 |
| 7.0.0 | 2019-08-01 | 2019-10-22 | M78 | v12 |
| 8.0.0 | 2019-10-24 | 2020-02-04 | M80 | v12 |
| 9.0.0 | 2020-02-06 | 2020-04-28 | M82 | v12 |
| 9.0.0 | 2020-02-06 | 2020-03-12 | M82 | v12 |
| 10.0.0 | TBD | TBD | TBD | TBD |

View File

@@ -1,29 +1,40 @@
# Mojave Dark Mode
# Supporting macOS Dark Mode
In macOS 10.14 Mojave, Apple introduced a new [system-wide dark mode](https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/dark-mode/)
for all macOS computers. If your app does have a dark mode, you can make your Electron app
follow the system-wide dark mode setting using [the nativeTheme api](../api/native-theme.md).
for all macOS computers. If your Electron app has a dark mode, you can make it follow the
system-wide dark mode setting using [the `nativeTheme` api](../api/native-theme.md).
In macOS 10.15 Catalina, Apple introduced a new "automatic" dark mode option for all macOS computers. In order
for the `nativeTheme.shouldUseDarkColors` and `Tray` APIs to work correctly in this mode on Catalina you need to either have `NSRequiresAquaSystemAppearance` set to `false` in your `Info.plist` file or be on Electron `>=7.0.0`.
In macOS 10.15 Catalina, Apple introduced a new "automatic" dark mode option for all macOS computers.
In order for the `nativeTheme.shouldUseDarkColors` and `Tray` APIs to work correctly in this mode on
Catalina, you need to either have `NSRequiresAquaSystemAppearance` set to `false` in your
`Info.plist` file, or be on Electron `>=7.0.0`. Both [Electron Packager][electron-packager] and
[Electron Forge][electron-forge] have a [`darwinDarkModeSupport` option][packager-darwindarkmode-api]
to automate the `Info.plist` changes during app build time.
## Automatically updating the native interfaces
"Native Interfaces" include the file picker, window border, dialogs, context menus and more; basically anything where
the UI comes from macOS and not your app. The default behavior as of Electron 7.0.0 is to opt in to this automatic
theming from the OS. If you wish to opt out you must set the `NSRequiresAquaSystemAppearance` key in the `Info.plist` file
to `true`. Please note that once Electron starts building against the 10.14 SDK it will not be possible for you to opt
out of this theming.
"Native Interfaces" include the file picker, window border, dialogs, context menus and more; basically,
anything where the UI comes from macOS and not your app. As of Electron 7.0.0, the default behavior
is to opt in to this automatic theming from the OS. If you wish to opt out and are using Electron
&gt; 8.0.0, you must set the `NSRequiresAquaSystemAppearance` key in the `Info.plist` file to `true`.
Please note that Electron 8.0.0 and above will not let your opt out of this theming, due to the use
of the macOS 10.14 SDK.
## Automatically updating your own interfaces
If your app has its own dark mode you should toggle it on and off in sync with the system's dark mode setting. You can do
this by listening for the theme updated event on Electron's `nativeTheme` module. E.g.
If your app has its own dark mode, you should toggle it on and off in sync with the system's dark
mode setting. You can do this by listening for the theme updated event on Electron's `nativeTheme` module.
```js
For example:
```javascript
const { nativeTheme } = require('electron')
nativeTheme.on('updated', function theThemeHasChanged () {
updateMyAppTheme(nativeTheme.shouldUseDarkColors)
})
```
[electron-forge]: https://www.electronforge.io/
[electron-packager]: https://github.com/electron/electron-packager
[packager-darwindarkmode-api]: https://electron.github.io/electron-packager/master/interfaces/electronpackager.options.html#darwindarkmodesupport

View File

@@ -1,4 +1,4 @@
# Testing on Headless CI Systems (Travis CI, Jenkins)
# Testing on Headless CI Systems (Travis CI, Github Actions, Jenkins)
Being based on Chromium, Electron requires a display driver to function.
If Chromium can't find a display driver, Electron will fail to launch -
@@ -45,6 +45,10 @@ install:
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
```
### Github Actions
For Github Actions, a [Xvfb action is available](https://github.com/marketplace/actions/gabrielbb-xvfb-action).
### Jenkins
For Jenkins, a [Xvfb plugin is available](https://wiki.jenkins-ci.org/display/JENKINS/Xvfb+Plugin).

View File

@@ -21,7 +21,6 @@ auto_filenames = {
"docs/api/dock.md",
"docs/api/download-item.md",
"docs/api/environment-variables.md",
"docs/api/extensions.md",
"docs/api/file-object.md",
"docs/api/frameless-window.md",
"docs/api/global-shortcut.md",

View File

@@ -558,8 +558,11 @@ filenames = {
"shell/common/skia_util.h",
"shell/common/v8_value_converter.cc",
"shell/common/v8_value_converter.h",
"shell/renderer/api/context_bridge/render_frame_context_bridge_store.cc",
"shell/renderer/api/context_bridge/render_frame_context_bridge_store.h",
"shell/common/world_ids.h",
"shell/renderer/api/context_bridge/object_cache.cc",
"shell/renderer/api/context_bridge/object_cache.h",
"shell/renderer/api/context_bridge/render_frame_function_store.cc",
"shell/renderer/api/context_bridge/render_frame_function_store.h",
"shell/renderer/api/electron_api_context_bridge.cc",
"shell/renderer/api/electron_api_context_bridge.h",
"shell/renderer/api/electron_api_renderer_ipc.cc",
@@ -598,6 +601,8 @@ filenames = {
]
lib_sources_extensions = [
"shell/browser/extensions/api/i18n/i18n_api.cc",
"shell/browser/extensions/api/i18n/i18n_api.h",
"shell/browser/extensions/api/resources_private/resources_private_api.cc",
"shell/browser/extensions/api/resources_private/resources_private_api.h",
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.cc",
@@ -616,6 +621,8 @@ filenames = {
"shell/browser/extensions/electron_extension_host_delegate.h",
"shell/browser/extensions/electron_extension_loader.cc",
"shell/browser/extensions/electron_extension_loader.h",
"shell/browser/extensions/electron_extension_message_filter.cc",
"shell/browser/extensions/electron_extension_message_filter.h",
"shell/browser/extensions/electron_extension_system.cc",
"shell/browser/extensions/electron_extension_system.h",
"shell/browser/extensions/electron_extension_system_factory.cc",

View File

@@ -44,7 +44,7 @@ hunspell_dictionaries = [
"//third_party/hunspell_dictionaries/ta-IN-3-0.bdic",
"//third_party/hunspell_dictionaries/tg-TG-5-0.bdic",
"//third_party/hunspell_dictionaries/tr-TR-4-0.bdic",
"//third_party/hunspell_dictionaries/uk-UA-3-0.bdic",
"//third_party/hunspell_dictionaries/uk-UA-4-0.bdic",
"//third_party/hunspell_dictionaries/vi-VN-3-0.bdic",
"//third_party/hunspell_dictionaries/xx-XX-3-0.bdic",
]

View File

@@ -1,21 +1,44 @@
import * as fs from 'fs'
import * as path from 'path'
import * as fs from 'fs';
import * as path from 'path';
import { deprecate, Menu } from 'electron'
import { EventEmitter } from 'events'
import { Menu } from 'electron';
import { EventEmitter } from 'events';
const bindings = process.electronBinding('app')
const commandLine = process.electronBinding('command_line')
const { app, App } = bindings
const bindings = process.electronBinding('app');
const commandLine = process.electronBinding('command_line');
const { app, App } = bindings;
// Only one app object permitted.
export default app
export default app;
let dockMenu: Electron.Menu | null = null
let dockMenu: Electron.Menu | null = null;
// App is an EventEmitter.
Object.setPrototypeOf(App.prototype, EventEmitter.prototype)
EventEmitter.call(app as any)
Object.setPrototypeOf(App.prototype, EventEmitter.prototype);
EventEmitter.call(app as any);
// Properties.
const nativeASGetter = app.isAccessibilitySupportEnabled;
const nativeASSetter = app.setAccessibilitySupportEnabled;
Object.defineProperty(App.prototype, 'accessibilitySupportEnabled', {
get: () => nativeASGetter.call(app),
set: (enabled) => nativeASSetter.call(app, enabled)
});
const nativeBCGetter = app.getBadgeCount;
const nativeBCSetter = app.setBadgeCount;
Object.defineProperty(App.prototype, 'badgeCount', {
get: () => nativeBCGetter.call(app),
set: (count) => nativeBCSetter.call(app, count)
});
const nativeNGetter = app.getName;
const nativeNSetter = app.setName;
Object.defineProperty(App.prototype, 'name', {
get: () => nativeNGetter.call(app),
set: (name) => nativeNSetter.call(app, name)
});
Object.assign(app, {
commandLine: {
@@ -24,99 +47,94 @@ Object.assign(app, {
appendSwitch: (theSwitch: string, value?: string) => commandLine.appendSwitch(String(theSwitch), typeof value === 'undefined' ? value : String(value)),
appendArgument: (arg: string) => commandLine.appendArgument(String(arg))
} as Electron.CommandLine
})
});
// we define this here because it'd be overly complicated to
// do in native land
Object.defineProperty(app, 'applicationMenu', {
get () {
return Menu.getApplicationMenu()
return Menu.getApplicationMenu();
},
set (menu: Electron.Menu | null) {
return Menu.setApplicationMenu(menu)
return Menu.setApplicationMenu(menu);
}
})
});
App.prototype.isPackaged = (() => {
const execFile = path.basename(process.execPath).toLowerCase()
const execFile = path.basename(process.execPath).toLowerCase();
if (process.platform === 'win32') {
return execFile !== 'electron.exe'
return execFile !== 'electron.exe';
}
return execFile !== 'electron'
})()
return execFile !== 'electron';
})();
app._setDefaultAppPaths = (packagePath) => {
// Set the user path according to application's name.
app.setPath('userData', path.join(app.getPath('appData'), app.name!))
app.setPath('userCache', path.join(app.getPath('cache'), app.name!))
app.setAppPath(packagePath)
app.setPath('userData', path.join(app.getPath('appData'), app.name!));
app.setPath('userCache', path.join(app.getPath('cache'), app.name!));
app.setAppPath(packagePath);
// Add support for --user-data-dir=
if (app.commandLine.hasSwitch('user-data-dir')) {
const userDataDir = app.commandLine.getSwitchValue('user-data-dir')
if (path.isAbsolute(userDataDir)) app.setPath('userData', userDataDir)
const userDataDir = app.commandLine.getSwitchValue('user-data-dir');
if (path.isAbsolute(userDataDir)) app.setPath('userData', userDataDir);
}
}
};
if (process.platform === 'darwin') {
const setDockMenu = app.dock!.setMenu
const setDockMenu = app.dock!.setMenu;
app.dock!.setMenu = (menu) => {
dockMenu = menu
setDockMenu(menu)
}
app.dock!.getMenu = () => dockMenu
dockMenu = menu;
setDockMenu(menu);
};
app.dock!.getMenu = () => dockMenu;
}
if (process.platform === 'linux') {
const patternVmRSS = /^VmRSS:\s*(\d+) kB$/m
const patternVmHWM = /^VmHWM:\s*(\d+) kB$/m
const patternVmRSS = /^VmRSS:\s*(\d+) kB$/m;
const patternVmHWM = /^VmHWM:\s*(\d+) kB$/m;
const getStatus = (pid: number) => {
try {
return fs.readFileSync(`/proc/${pid}/status`, 'utf8')
return fs.readFileSync(`/proc/${pid}/status`, 'utf8');
} catch {
return ''
return '';
}
}
};
const getEntry = (file: string, pattern: RegExp) => {
const match = file.match(pattern)
return match ? parseInt(match[1], 10) : 0
}
const match = file.match(pattern);
return match ? parseInt(match[1], 10) : 0;
};
const getProcessMemoryInfo = (pid: number) => {
const file = getStatus(pid)
const file = getStatus(pid);
return {
workingSetSize: getEntry(file, patternVmRSS),
peakWorkingSetSize: getEntry(file, patternVmHWM)
}
}
};
};
const nativeFn = app.getAppMetrics
const nativeFn = app.getAppMetrics;
app.getAppMetrics = () => {
const metrics = nativeFn.call(app)
const metrics = nativeFn.call(app);
for (const metric of metrics) {
metric.memory = getProcessMemoryInfo(metric.pid)
metric.memory = getProcessMemoryInfo(metric.pid);
}
return metrics
}
return metrics;
};
}
// Routes the events to webContents.
const events = ['certificate-error', 'select-client-certificate']
const events = ['certificate-error', 'select-client-certificate'];
for (const name of events) {
app.on(name as 'certificate-error', (event, webContents, ...args: any[]) => {
webContents.emit(name, event, ...args)
})
webContents.emit(name, event, ...args);
});
}
// Property Deprecations
deprecate.fnToProperty(App.prototype, 'accessibilitySupportEnabled', '_isAccessibilitySupportEnabled', '_setAccessibilitySupportEnabled')
deprecate.fnToProperty(App.prototype, 'badgeCount', '_getBadgeCount', '_setBadgeCount')
deprecate.fnToProperty(App.prototype, 'name', '_getName', '_setName')
// Wrappers for native classes.
const { DownloadItem } = process.electronBinding('download_item')
Object.setPrototypeOf(DownloadItem.prototype, EventEmitter.prototype)
const { DownloadItem } = process.electronBinding('download_item');
Object.setPrototypeOf(DownloadItem.prototype, EventEmitter.prototype);

View File

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

View File

@@ -1,10 +1,10 @@
'use strict'
'use strict';
const EventEmitter = require('events').EventEmitter
const { autoUpdater, AutoUpdater } = process.electronBinding('auto_updater')
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)
Object.setPrototypeOf(AutoUpdater.prototype, EventEmitter.prototype);
EventEmitter.call(autoUpdater);
module.exports = autoUpdater
module.exports = autoUpdater;

View File

@@ -1,74 +1,74 @@
'use strict'
'use strict';
const { app } = require('electron')
const { EventEmitter } = require('events')
const squirrelUpdate = require('@electron/internal/browser/api/auto-updater/squirrel-update-win')
const { app } = require('electron');
const { EventEmitter } = require('events');
const squirrelUpdate = require('@electron/internal/browser/api/auto-updater/squirrel-update-win');
class AutoUpdater extends EventEmitter {
quitAndInstall () {
if (!this.updateAvailable) {
return this.emitError('No update available, can\'t quit and install')
return this.emitError('No update available, can\'t quit and install');
}
squirrelUpdate.processStart()
app.quit()
squirrelUpdate.processStart();
app.quit();
}
getFeedURL () {
return this.updateURL
return this.updateURL;
}
setFeedURL (options) {
let updateURL
let updateURL;
if (typeof options === 'object') {
if (typeof options.url === 'string') {
updateURL = options.url
updateURL = options.url;
} else {
throw new Error('Expected options object to contain a \'url\' string property in setFeedUrl call')
throw new Error('Expected options object to contain a \'url\' string property in setFeedUrl call');
}
} else if (typeof options === 'string') {
updateURL = options
updateURL = options;
} else {
throw new Error('Expected an options object with a \'url\' property to be provided')
throw new Error('Expected an options object with a \'url\' property to be provided');
}
this.updateURL = updateURL
this.updateURL = updateURL;
}
checkForUpdates () {
if (!this.updateURL) {
return this.emitError('Update URL is not set')
return this.emitError('Update URL is not set');
}
if (!squirrelUpdate.supported()) {
return this.emitError('Can not find Squirrel')
return this.emitError('Can not find Squirrel');
}
this.emit('checking-for-update')
this.emit('checking-for-update');
squirrelUpdate.checkForUpdate(this.updateURL, (error, update) => {
if (error != null) {
return this.emitError(error)
return this.emitError(error);
}
if (update == null) {
return this.emit('update-not-available')
return this.emit('update-not-available');
}
this.updateAvailable = true
this.emit('update-available')
this.updateAvailable = true;
this.emit('update-available');
squirrelUpdate.update(this.updateURL, (error) => {
if (error != null) {
return this.emitError(error)
return this.emitError(error);
}
const { releaseNotes, version } = update
const { releaseNotes, version } = update;
// Date is not available on Windows, so fake it.
const date = new Date()
const date = new Date();
this.emit('update-downloaded', {}, releaseNotes, version, date, this.updateURL, () => {
this.quitAndInstall()
})
})
})
this.quitAndInstall();
});
});
});
}
// Private: Emit both error object and message, this is to keep compatibility
// with Old APIs.
emitError (message) {
this.emit('error', new Error(message), message)
this.emit('error', new Error(message), message);
}
}
module.exports = new AutoUpdater()
module.exports = new AutoUpdater();

View File

@@ -1,24 +1,24 @@
'use strict'
'use strict';
const fs = require('fs')
const path = require('path')
const spawn = require('child_process').spawn
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)
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 = []
let spawnedProcess
const updateExe = path.resolve(appFolder, '..', 'Update.exe');
const exeName = path.basename(process.execPath);
let spawnedArgs = [];
let spawnedProcess;
const isSameArgs = (args) => 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, detached, callback) {
let error, errorEmitted, stderr, stdout
let error, errorEmitted, stderr, stdout;
try {
// Ensure we don't spawn multiple squirrel processes
@@ -28,92 +28,92 @@ const spawnUpdate = function (args, detached, callback) {
if (spawnedProcess && !isSameArgs(args)) {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(`AutoUpdater process with arguments ${args} is already running`)
return callback(`AutoUpdater process with arguments ${args} is already running`);
} else if (!spawnedProcess) {
spawnedProcess = spawn(updateExe, args, {
detached: detached,
windowsHide: true
})
spawnedArgs = args || []
});
spawnedArgs = args || [];
}
} catch (error1) {
error = error1
error = error1;
// Shouldn't happen, but still guard it.
process.nextTick(function () {
return callback(error)
})
return
return callback(error);
});
return;
}
stdout = ''
stderr = ''
stdout = '';
stderr = '';
spawnedProcess.stdout.on('data', (data) => { stdout += data })
spawnedProcess.stderr.on('data', (data) => { stderr += data })
spawnedProcess.stdout.on('data', (data) => { stdout += data; });
spawnedProcess.stderr.on('data', (data) => { stderr += data; });
errorEmitted = false
errorEmitted = false;
spawnedProcess.on('error', (error) => {
errorEmitted = true
callback(error)
})
errorEmitted = true;
callback(error);
});
return spawnedProcess.on('exit', function (code, signal) {
spawnedProcess = undefined
spawnedArgs = []
spawnedProcess = undefined;
spawnedArgs = [];
// We may have already emitted an error.
if (errorEmitted) {
return
return;
}
// Process terminated with error.
if (code !== 0) {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(`Command failed: ${signal != null ? signal : code}\n${stderr}`)
return callback(`Command failed: ${signal != null ? signal : code}\n${stderr}`);
}
// Success.
callback(null, stdout)
})
}
callback(null, stdout);
});
};
// Start an instance of the installed app.
exports.processStart = function () {
return spawnUpdate(['--processStartAndWait', exeName], true, function () {})
}
return spawnUpdate(['--processStartAndWait', exeName], true, function () {});
};
// Download the releases specified by the URL and write new results to stdout.
exports.checkForUpdate = function (updateURL, callback) {
return spawnUpdate(['--checkForUpdate', updateURL], false, function (error, stdout) {
let ref, ref1, update
let ref, ref1, update;
if (error != null) {
return callback(error)
return callback(error);
}
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() : void 0 : void 0 : void 0
const json = stdout.trim().split('\n').pop();
update = (ref = JSON.parse(json)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : void 0 : void 0 : void 0;
} catch {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(`Invalid result:\n${stdout}`)
return callback(`Invalid result:\n${stdout}`);
}
return callback(null, update)
})
}
return callback(null, update);
});
};
// Update the application to the latest remote version specified by URL.
exports.update = function (updateURL, callback) {
return spawnUpdate(['--update', updateURL], false, callback)
}
return spawnUpdate(['--update', updateURL], false, callback);
};
// Is the Update.exe installed with the current application?
exports.supported = function () {
try {
fs.accessSync(updateExe, fs.R_OK)
return true
fs.accessSync(updateExe, fs.R_OK);
return true;
} catch {
return false
return false;
}
}
};

View File

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

View File

@@ -1,29 +1,49 @@
'use strict'
'use strict';
const electron = require('electron')
const { WebContentsView, TopLevelWindow, deprecate } = electron
const { BrowserWindow } = process.electronBinding('window')
const electron = require('electron');
const { WebContentsView, TopLevelWindow, deprecate } = electron;
const { BrowserWindow } = process.electronBinding('window');
Object.setPrototypeOf(BrowserWindow.prototype, TopLevelWindow.prototype)
Object.setPrototypeOf(BrowserWindow.prototype, TopLevelWindow.prototype);
BrowserWindow.prototype._init = function () {
// Call parent class's _init.
TopLevelWindow.prototype._init.call(this)
TopLevelWindow.prototype._init.call(this);
// Avoid recursive require.
const { app } = electron
const { app } = electron;
// Create WebContentsView.
this.setContentView(new WebContentsView(this.webContents))
this.setContentView(new WebContentsView(this.webContents));
const nativeSetBounds = this.setBounds
const nativeSetBounds = this.setBounds;
this.setBounds = (bounds, ...opts) => {
bounds = {
...this.getBounds(),
...bounds
};
nativeSetBounds.call(this, bounds, ...opts);
};
// window.resizeTo(...)
// window.moveTo(...)
this.webContents.on('move', (event, size) => {
this.setBounds(size);
});
// Hide the auto-hide menu when webContents is focused.
this.webContents.on('activate', () => {
if (process.platform !== 'darwin' && this.autoHideMenuBar && this.isMenuBarVisible()) {
this.setMenuBarVisibility(false);
}
nativeSetBounds.call(this, bounds, ...opts)
}
});
// Change window title to page title.
this.webContents.on('page-title-updated', (event, title, ...args) => {
// Route the event to BrowserWindow.
this.emit('page-title-updated', event, title, ...args);
if (!this.isDestroyed() && !event.defaultPrevented) this.setTitle(title);
});
// 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
@@ -34,144 +54,172 @@ BrowserWindow.prototype._init = function () {
// 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()
})
this.focus();
});
// Redirect focus/blur event to app instance too.
this.on('blur', (event) => {
app.emit('browser-window-blur', event, this)
})
app.emit('browser-window-blur', event, this);
});
this.on('focus', (event) => {
app.emit('browser-window-focus', event, this)
})
app.emit('browser-window-focus', event, this);
});
// Subscribe to visibilityState changes and pass to renderer process.
let isVisible = this.isVisible() && !this.isMinimized()
let isVisible = this.isVisible() && !this.isMinimized();
const visibilityChanged = () => {
const newState = this.isVisible() && !this.isMinimized()
const newState = this.isVisible() && !this.isMinimized();
if (isVisible !== newState) {
isVisible = newState
const visibilityState = isVisible ? 'visible' : 'hidden'
this.webContents.emit('-window-visibility-change', visibilityState)
isVisible = newState;
const visibilityState = isVisible ? 'visible' : 'hidden';
this.webContents.emit('-window-visibility-change', visibilityState);
}
}
};
const visibilityEvents = ['show', 'hide', 'minimize', 'maximize', 'restore']
const visibilityEvents = ['show', 'hide', 'minimize', 'maximize', 'restore'];
for (const event of visibilityEvents) {
this.on(event, visibilityChanged)
this.on(event, visibilityChanged);
}
// Notify the creation of the window.
const event = process.electronBinding('event').createEmpty()
app.emit('browser-window-created', event, this)
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
return this.webContents.devToolsWebContents;
}
})
}
});
// Properties
Object.defineProperty(this, 'autoHideMenuBar', {
get: () => this.isMenuBarAutoHide(),
set: (autoHide) => this.setAutoHideMenuBar(autoHide)
});
Object.defineProperty(this, 'minimizable', {
get: () => this.isMinimizable(),
set: (min) => this.setMinimizable(min)
});
Object.defineProperty(this, 'maximizable', {
get: () => this.isMaximizable(),
set: (max) => this.setMaximizable(max)
});
Object.defineProperty(this, 'resizable', {
get: () => this.isResizable(),
set: (res) => this.setResizable(res)
});
Object.defineProperty(this, 'fullScreenable', {
get: () => this.isFullScreenable(),
set: (full) => this.setFullScreenable(full)
});
Object.defineProperty(this, 'closable', {
get: () => this.isClosable(),
set: (close) => this.setClosable(close)
});
Object.defineProperty(this, 'movable', {
get: () => this.isMovable(),
set: (move) => this.setMovable(move)
});
};
const isBrowserWindow = (win) => {
return win && win.constructor.name === 'BrowserWindow'
}
return win && win.constructor.name === 'BrowserWindow';
};
BrowserWindow.fromId = (id) => {
const win = TopLevelWindow.fromId(id)
return isBrowserWindow(win) ? win : null
}
const win = TopLevelWindow.fromId(id);
return isBrowserWindow(win) ? win : null;
};
BrowserWindow.getAllWindows = () => {
return TopLevelWindow.getAllWindows().filter(isBrowserWindow)
}
return TopLevelWindow.getAllWindows().filter(isBrowserWindow);
};
BrowserWindow.getFocusedWindow = () => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.isFocused() || window.isDevToolsFocused()) return window
if (window.isFocused() || window.isDevToolsFocused()) return window;
}
return null
}
return null;
};
BrowserWindow.fromWebContents = (webContents) => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.webContents && window.webContents.equal(webContents)) return window
if (window.webContents && window.webContents.equal(webContents)) return window;
}
return null
}
return null;
};
BrowserWindow.fromBrowserView = (browserView) => {
for (const window of BrowserWindow.getAllWindows()) {
if (window.getBrowserView() === browserView) return window
if (window.getBrowserView() === browserView) return window;
}
return null
}
return null;
};
// Helpers.
Object.assign(BrowserWindow.prototype, {
loadURL (...args) {
return this.webContents.loadURL(...args)
return this.webContents.loadURL(...args);
},
getURL (...args) {
return this.webContents.getURL()
return this.webContents.getURL();
},
loadFile (...args) {
return this.webContents.loadFile(...args)
return this.webContents.loadFile(...args);
},
reload (...args) {
return this.webContents.reload(...args)
return this.webContents.reload(...args);
},
send (...args) {
return this.webContents.send(...args)
return this.webContents.send(...args);
},
openDevTools (...args) {
return this.webContents.openDevTools(...args)
return this.webContents.openDevTools(...args);
},
closeDevTools () {
return this.webContents.closeDevTools()
return this.webContents.closeDevTools();
},
isDevToolsOpened () {
return this.webContents.isDevToolsOpened()
return this.webContents.isDevToolsOpened();
},
isDevToolsFocused () {
return this.webContents.isDevToolsFocused()
return this.webContents.isDevToolsFocused();
},
toggleDevTools () {
return this.webContents.toggleDevTools()
return this.webContents.toggleDevTools();
},
inspectElement (...args) {
return this.webContents.inspectElement(...args)
return this.webContents.inspectElement(...args);
},
inspectSharedWorker () {
return this.webContents.inspectSharedWorker()
return this.webContents.inspectSharedWorker();
},
inspectServiceWorker () {
return this.webContents.inspectServiceWorker()
return this.webContents.inspectServiceWorker();
},
showDefinitionForSelection () {
return this.webContents.showDefinitionForSelection()
return this.webContents.showDefinitionForSelection();
},
capturePage (...args) {
return this.webContents.capturePage(...args)
return this.webContents.capturePage(...args);
},
setTouchBar (touchBar) {
electron.TouchBar._setOnWindow(touchBar, this)
electron.TouchBar._setOnWindow(touchBar, this);
},
setBackgroundThrottling (allowed) {
this.webContents.setBackgroundThrottling(allowed)
this.webContents.setBackgroundThrottling(allowed);
}
})
});
// Deprecations
deprecate.fnToProperty(BrowserWindow.prototype, 'autoHideMenuBar', '_isMenuBarAutoHide', '_setAutoHideMenuBar')
deprecate.fnToProperty(BrowserWindow.prototype, 'minimizable', '_isMinimizable', '_setMinimizable')
deprecate.fnToProperty(BrowserWindow.prototype, 'maximizable', '_isMaximizable', '_setMaximizable')
deprecate.fnToProperty(BrowserWindow.prototype, 'resizable', '_isResizable', '_setResizable')
deprecate.fnToProperty(BrowserWindow.prototype, 'fullScreenable', '_isFullScreenable', '_setFullScreenable')
deprecate.fnToProperty(BrowserWindow.prototype, 'closable', '_isClosable', '_setClosable')
deprecate.fnToProperty(BrowserWindow.prototype, 'movable', '_isMovable', '_setMovable')
module.exports = BrowserWindow
module.exports = BrowserWindow;

View File

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

View File

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

View File

@@ -1,13 +1,13 @@
'use strict'
'use strict';
const { app, BrowserWindow, deprecate } = require('electron')
const binding = process.electronBinding('dialog')
const v8Util = process.electronBinding('v8_util')
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,
@@ -15,7 +15,7 @@ const saveFileDialogProperties = {
treatPackageAsDirectory: 1 << 2,
showOverwriteConfirmation: 1 << 3,
dontAddToRecent: 1 << 4
}
};
const openFileDialogProperties = {
openFile: 1 << 0,
@@ -27,15 +27,15 @@ const openFileDialogProperties = {
noResolveAliases: 1 << 6, // macOS
treatPackageAsDirectory: 1 << 7, // macOS
dontAddToRecent: 1 << 8 // Windows
}
};
const normalizeAccessKey = (text) => {
if (typeof text !== 'string') return 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')
return text.replace(/&(&?)/g, '$1');
}
// Linux uses a single underscore as an access key prefix so escape
@@ -44,41 +44,41 @@ const normalizeAccessKey = (text) => {
// a single underscore
if (process.platform === 'linux') {
return text.replace(/_/g, '__').replace(/&(.?)/g, (match, after) => {
if (after === '&') return after
return `_${after}`
})
if (after === '&') return after;
return `_${after}`;
});
}
return text
}
return text;
};
const checkAppInitialized = function () {
if (!app.isReady()) {
throw new Error('dialog module can only be used after app is ready')
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
const dialogPropertiesTypes = (type === DialogType.OPEN) ? openFileDialogProperties : saveFileDialogProperties;
let dialogProperties = 0;
for (const prop in dialogPropertiesTypes) {
if (properties.includes(prop)) {
dialogProperties |= dialogPropertiesTypes[prop]
dialogProperties |= dialogPropertiesTypes[prop];
}
}
return dialogProperties
}
return dialogProperties;
};
const saveDialog = (sync, window, options) => {
checkAppInitialized()
checkAppInitialized();
if (window && window.constructor !== BrowserWindow) {
options = window
window = null
options = window;
window = null;
}
if (options == null) options = { title: 'Save' }
if (options == null) options = { title: 'Save' };
const {
buttonLabel = '',
@@ -90,33 +90,33 @@ const saveDialog = (sync, window, options) => {
securityScopedBookmarks = false,
nameFieldLabel = '',
showsTagField = true
} = options
} = 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')
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)
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)
}
return (sync) ? binding.showSaveDialogSync(settings) : binding.showSaveDialog(settings);
};
const openDialog = (sync, window, options) => {
checkAppInitialized()
checkAppInitialized();
if (window && window.constructor !== BrowserWindow) {
options = window
window = null
options = window;
window = null;
}
if (options == null) {
options = {
title: 'Open',
properties: ['openFile']
}
};
}
const {
@@ -127,33 +127,33 @@ const openDialog = (sync, window, options) => {
title = '',
message = '',
securityScopedBookmarks = false
} = options
} = options;
if (!Array.isArray(properties)) throw new TypeError('Properties must be an array')
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')
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)
const settings = { title, buttonLabel, defaultPath, filters, message, securityScopedBookmarks, window };
settings.properties = setupDialogProperties(DialogType.OPEN, properties);
return (sync) ? binding.showOpenDialogSync(settings) : binding.showOpenDialog(settings)
}
return (sync) ? binding.showOpenDialogSync(settings) : binding.showOpenDialog(settings);
};
const messageBox = (sync, window, options) => {
checkAppInitialized()
checkAppInitialized();
if (window && window.constructor !== BrowserWindow) {
options = window
window = null
options = window;
window = null;
}
if (options == null) options = { type: 'none' }
if (options == null) options = { type: 'none' };
const messageBoxTypes = ['none', 'info', 'warning', 'error', 'question']
const messageBoxOptions = { noLink: 1 << 0 }
const messageBoxTypes = ['none', 'info', 'warning', 'error', 'question'];
const messageBoxOptions = { noLink: 1 << 0 };
let {
buttons = [],
@@ -167,32 +167,32 @@ const messageBox = (sync, window, options) => {
message = '',
title = '',
type = 'none'
} = options
} = 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')
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
checkboxChecked = !!checkboxChecked;
if (checkboxChecked && !checkboxLabel) {
throw new Error('checkboxChecked requires that checkboxLabel also be passed')
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
cancelId = (defaultId === 0 && buttons.length > 1) ? 1 : 0;
for (let i = 0; i < buttons.length; i++) {
const text = buttons[i].toLowerCase()
const text = buttons[i].toLowerCase();
if (text === 'cancel' || text === 'no') {
cancelId = i
break
cancelId = i;
break;
}
}
}
@@ -210,57 +210,57 @@ const messageBox = (sync, window, options) => {
checkboxLabel,
checkboxChecked,
icon
}
};
if (sync) {
return binding.showMessageBoxSync(settings)
return binding.showMessageBoxSync(settings);
} else {
return binding.showMessageBox(settings)
return binding.showMessageBox(settings);
}
}
};
module.exports = {
showOpenDialog: function (window, options) {
return openDialog(false, window, options)
return openDialog(false, window, options);
},
showOpenDialogSync: function (window, options) {
return openDialog(true, window, options)
return openDialog(true, window, options);
},
showSaveDialog: function (window, options) {
return saveDialog(false, window, options)
return saveDialog(false, window, options);
},
showSaveDialogSync: function (window, options) {
return saveDialog(true, window, options)
return saveDialog(true, window, options);
},
showMessageBox: function (window, options) {
return messageBox(false, window, options)
return messageBox(false, window, options);
},
showMessageBoxSync: function (window, options) {
return messageBox(true, window, options)
return messageBox(true, window, options);
},
showErrorBox: function (...args) {
return binding.showErrorBox(...args)
return binding.showErrorBox(...args);
},
showCertificateTrustDialog: function (window, options) {
if (window && window.constructor !== BrowserWindow) options = window
if (window && window.constructor !== BrowserWindow) options = window;
if (options == null || typeof options !== 'object') {
throw new TypeError('options must be an object')
throw new TypeError('options must be an object');
}
const { certificate, message = '' } = options
const { certificate, message = '' } = options;
if (certificate == null || typeof certificate !== 'object') {
throw new TypeError('certificate must be an object')
throw new TypeError('certificate must be an object');
}
if (typeof message !== 'string') throw new TypeError('message must be a string')
if (typeof message !== 'string') throw new TypeError('message must be a string');
return binding.showCertificateTrustDialog(window, certificate, message)
return binding.showCertificateTrustDialog(window, certificate, message);
}
}
};

View File

@@ -1,8 +1,8 @@
import { defineProperties } from '@electron/internal/common/define-properties'
import { commonModuleList } from '@electron/internal/common/api/module-list'
import { browserModuleList } from '@electron/internal/browser/api/module-list'
import { defineProperties } from '@electron/internal/common/define-properties';
import { commonModuleList } from '@electron/internal/common/api/module-list';
import { browserModuleList } from '@electron/internal/browser/api/module-list';
module.exports = {}
module.exports = {};
defineProperties(module.exports, commonModuleList)
defineProperties(module.exports, browserModuleList)
defineProperties(module.exports, commonModuleList);
defineProperties(module.exports, browserModuleList);

View File

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

View File

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

View File

@@ -1,8 +1,8 @@
import { IpcMainImpl } from '@electron/internal/browser/ipc-main-impl'
import { IpcMainImpl } from '@electron/internal/browser/ipc-main-impl';
const ipcMain = new IpcMainImpl()
const ipcMain = new IpcMainImpl();
// Do not throw exception when channel name is "error".
ipcMain.on('error', () => {})
ipcMain.on('error', () => {});
export default ipcMain
export default ipcMain;

View File

@@ -1,15 +1,15 @@
'use strict'
'use strict';
const { app } = require('electron')
const { app } = require('electron');
const isMac = process.platform === 'darwin'
const isWindows = process.platform === 'win32'
const isLinux = process.platform === 'linux'
const isMac = process.platform === 'darwin';
const isWindows = process.platform === 'win32';
const isLinux = process.platform === 'linux';
const roles = {
about: {
get label () {
return isLinux ? 'About' : `About ${app.name}`
return isLinux ? 'About' : `About ${app.name}`;
}
},
close: {
@@ -38,7 +38,7 @@ const roles = {
accelerator: 'Shift+CmdOrCtrl+R',
nonNativeMacOSRole: true,
windowMethod: (window) => {
window.webContents.reloadIgnoringCache()
window.webContents.reloadIgnoringCache();
}
},
front: {
@@ -49,7 +49,7 @@ const roles = {
},
hide: {
get label () {
return `Hide ${app.name}`
return `Hide ${app.name}`;
},
accelerator: 'Command+H'
},
@@ -77,9 +77,9 @@ const roles = {
quit: {
get label () {
switch (process.platform) {
case 'darwin': return `Quit ${app.name}`
case 'win32': return 'Exit'
default: return 'Quit'
case 'darwin': return `Quit ${app.name}`;
case 'win32': return 'Exit';
default: return 'Quit';
}
},
accelerator: isWindows ? undefined : 'CommandOrControl+Q',
@@ -101,7 +101,7 @@ const roles = {
accelerator: 'CommandOrControl+0',
nonNativeMacOSRole: true,
webContentsMethod: (webContents) => {
webContents.zoomLevel = 0
webContents.zoomLevel = 0;
}
},
selectall: {
@@ -134,7 +134,7 @@ const roles = {
label: 'Toggle Full Screen',
accelerator: isMac ? 'Control+Command+F' : 'F11',
windowMethod: (window) => {
window.setFullScreen(!window.isFullScreen())
window.setFullScreen(!window.isFullScreen());
}
},
undo: {
@@ -156,7 +156,7 @@ const roles = {
accelerator: 'CommandOrControl+Plus',
nonNativeMacOSRole: true,
webContentsMethod: (webContents) => {
webContents.zoomLevel += 0.5
webContents.zoomLevel += 0.5;
}
},
zoomout: {
@@ -164,13 +164,13 @@ const roles = {
accelerator: 'CommandOrControl+-',
nonNativeMacOSRole: true,
webContentsMethod: (webContents) => {
webContents.zoomLevel -= 0.5
webContents.zoomLevel -= 0.5;
}
},
// App submenu should be used for Mac only
appmenu: {
get label () {
return app.name
return app.name;
},
submenu: [
{ role: 'about' },
@@ -249,71 +249,71 @@ const roles = {
])
]
}
}
};
exports.roleList = roles
exports.roleList = roles;
const canExecuteRole = (role) => {
if (!roles.hasOwnProperty(role)) return false
if (!isMac) return true
if (!roles.hasOwnProperty(role)) return false;
if (!isMac) return true;
// macOS handles all roles natively except for a few
return roles[role].nonNativeMacOSRole
}
return roles[role].nonNativeMacOSRole;
};
exports.getDefaultLabel = (role) => {
return roles.hasOwnProperty(role) ? roles[role].label : ''
}
return roles.hasOwnProperty(role) ? roles[role].label : '';
};
exports.getDefaultAccelerator = (role) => {
if (roles.hasOwnProperty(role)) return roles[role].accelerator
}
if (roles.hasOwnProperty(role)) return roles[role].accelerator;
};
exports.shouldRegisterAccelerator = (role) => {
const hasRoleRegister = roles.hasOwnProperty(role) && roles[role].registerAccelerator !== undefined
return hasRoleRegister ? roles[role].registerAccelerator : true
}
const hasRoleRegister = roles.hasOwnProperty(role) && roles[role].registerAccelerator !== undefined;
return hasRoleRegister ? roles[role].registerAccelerator : true;
};
exports.getDefaultSubmenu = (role) => {
if (!roles.hasOwnProperty(role)) return
if (!roles.hasOwnProperty(role)) return;
let { submenu } = roles[role]
let { submenu } = roles[role];
// remove null items from within the submenu
if (Array.isArray(submenu)) {
submenu = submenu.filter((item) => item != null)
submenu = submenu.filter((item) => item != null);
}
return submenu
}
return submenu;
};
exports.execute = (role, focusedWindow, focusedWebContents) => {
if (!canExecuteRole(role)) return false
if (!canExecuteRole(role)) return false;
const { appMethod, webContentsMethod, windowMethod } = roles[role]
const { appMethod, webContentsMethod, windowMethod } = roles[role];
if (appMethod) {
app[appMethod]()
return true
app[appMethod]();
return true;
}
if (windowMethod && focusedWindow != null) {
if (typeof windowMethod === 'function') {
windowMethod(focusedWindow)
windowMethod(focusedWindow);
} else {
focusedWindow[windowMethod]()
focusedWindow[windowMethod]();
}
return true
return true;
}
if (webContentsMethod && focusedWebContents != null) {
if (typeof webContentsMethod === 'function') {
webContentsMethod(focusedWebContents)
webContentsMethod(focusedWebContents);
} else {
focusedWebContents[webContentsMethod]()
focusedWebContents[webContentsMethod]();
}
return true
return true;
}
return false
}
return false;
};

View File

@@ -1,87 +1,87 @@
'use strict'
'use strict';
const roles = require('@electron/internal/browser/api/menu-item-roles')
const roles = require('@electron/internal/browser/api/menu-item-roles');
let nextCommandId = 0
let nextCommandId = 0;
const MenuItem = function (options) {
const { Menu } = require('electron')
const { Menu } = require('electron');
// Preserve extra fields specified by user
for (const key in options) {
if (!(key in this)) this[key] = options[key]
if (!(key in this)) this[key] = options[key];
}
if (typeof this.role === 'string' || this.role instanceof String) {
this.role = this.role.toLowerCase()
this.role = this.role.toLowerCase();
}
this.submenu = this.submenu || roles.getDefaultSubmenu(this.role)
this.submenu = this.submenu || roles.getDefaultSubmenu(this.role);
if (this.submenu != null && this.submenu.constructor !== Menu) {
this.submenu = Menu.buildFromTemplate(this.submenu)
this.submenu = Menu.buildFromTemplate(this.submenu);
}
if (this.type == null && this.submenu != null) {
this.type = 'submenu'
this.type = 'submenu';
}
if (this.type === 'submenu' && (this.submenu == null || this.submenu.constructor !== Menu)) {
throw new Error('Invalid submenu')
throw new Error('Invalid submenu');
}
this.overrideReadOnlyProperty('type', 'normal')
this.overrideReadOnlyProperty('role')
this.overrideReadOnlyProperty('accelerator')
this.overrideReadOnlyProperty('icon')
this.overrideReadOnlyProperty('submenu')
this.overrideReadOnlyProperty('type', 'normal');
this.overrideReadOnlyProperty('role');
this.overrideReadOnlyProperty('accelerator');
this.overrideReadOnlyProperty('icon');
this.overrideReadOnlyProperty('submenu');
this.overrideProperty('label', roles.getDefaultLabel(this.role))
this.overrideProperty('sublabel', '')
this.overrideProperty('toolTip', '')
this.overrideProperty('enabled', true)
this.overrideProperty('visible', true)
this.overrideProperty('checked', false)
this.overrideProperty('acceleratorWorksWhenHidden', true)
this.overrideProperty('registerAccelerator', roles.shouldRegisterAccelerator(this.role))
this.overrideProperty('label', roles.getDefaultLabel(this.role));
this.overrideProperty('sublabel', '');
this.overrideProperty('toolTip', '');
this.overrideProperty('enabled', true);
this.overrideProperty('visible', true);
this.overrideProperty('checked', false);
this.overrideProperty('acceleratorWorksWhenHidden', true);
this.overrideProperty('registerAccelerator', roles.shouldRegisterAccelerator(this.role));
if (!MenuItem.types.includes(this.type)) {
throw new Error(`Unknown menu item type: ${this.type}`)
throw new Error(`Unknown menu item type: ${this.type}`);
}
this.overrideReadOnlyProperty('commandId', ++nextCommandId)
this.overrideReadOnlyProperty('commandId', ++nextCommandId);
const click = options.click
const click = options.click;
this.click = (event, focusedWindow, focusedWebContents) => {
// Manually flip the checked flags when clicked.
if (this.type === 'checkbox' || this.type === 'radio') {
this.checked = !this.checked
this.checked = !this.checked;
}
if (!roles.execute(this.role, focusedWindow, focusedWebContents)) {
if (typeof click === 'function') {
click(this, focusedWindow, event)
click(this, focusedWindow, event);
} else if (typeof this.selector === 'string' && process.platform === 'darwin') {
Menu.sendActionToFirstResponder(this.selector)
Menu.sendActionToFirstResponder(this.selector);
}
}
}
}
};
};
MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio'];
MenuItem.prototype.getDefaultRoleAccelerator = function () {
return roles.getDefaultAccelerator(this.role)
}
return roles.getDefaultAccelerator(this.role);
};
MenuItem.prototype.overrideProperty = function (name, defaultValue = null) {
if (this[name] == null) {
this[name] = defaultValue
this[name] = defaultValue;
}
}
};
MenuItem.prototype.overrideReadOnlyProperty = function (name, defaultValue) {
this.overrideProperty(name, defaultValue)
this.overrideProperty(name, defaultValue);
Object.defineProperty(this, name, {
enumerable: true,
writable: false,
value: this[name]
})
}
});
};
module.exports = MenuItem
module.exports = MenuItem;

View File

@@ -1,41 +1,41 @@
'use strict'
'use strict';
function splitArray (arr, predicate) {
const result = arr.reduce((multi, item) => {
const current = multi[multi.length - 1]
const current = multi[multi.length - 1];
if (predicate(item)) {
if (current.length > 0) multi.push([])
if (current.length > 0) multi.push([]);
} else {
current.push(item)
current.push(item);
}
return multi
}, [[]])
return multi;
}, [[]]);
if (result[result.length - 1].length === 0) {
return result.slice(0, result.length - 1)
return result.slice(0, result.length - 1);
}
return result
return result;
}
function joinArrays (arrays, joinIDs) {
return arrays.reduce((joined, arr, i) => {
if (i > 0 && arr.length) {
if (joinIDs.length > 0) {
joined.push(joinIDs[0])
joinIDs.splice(0, 1)
joined.push(joinIDs[0]);
joinIDs.splice(0, 1);
} else {
joined.push({ type: 'separator' })
joined.push({ type: 'separator' });
}
}
return joined.concat(arr)
}, [])
return joined.concat(arr);
}, []);
}
function pushOntoMultiMap (map, key, value) {
if (!map.has(key)) {
map.set(key, [])
map.set(key, []);
}
map.get(key).push(value)
map.get(key).push(value);
}
function indexOfGroupContainingID (groups, id, ignoreGroup) {
@@ -45,102 +45,102 @@ function indexOfGroupContainingID (groups, id, ignoreGroup) {
candidateGroup.some(
candidateItem => candidateItem.id === id
)
)
);
}
// Sort nodes topologically using a depth-first approach. Encountered cycles
// are broken.
function sortTopologically (originalOrder, edgesById) {
const sorted = []
const marked = new Set()
const sorted = [];
const marked = new Set();
const visit = (mark) => {
if (marked.has(mark)) return
marked.add(mark)
const edges = edgesById.get(mark)
if (marked.has(mark)) return;
marked.add(mark);
const edges = edgesById.get(mark);
if (edges != null) {
edges.forEach(visit)
edges.forEach(visit);
}
sorted.push(mark)
}
sorted.push(mark);
};
originalOrder.forEach(visit)
return sorted
originalOrder.forEach(visit);
return sorted;
}
function attemptToMergeAGroup (groups) {
for (let i = 0; i < groups.length; i++) {
const group = groups[i]
const group = groups[i];
for (const item of group) {
const toIDs = [...(item.before || []), ...(item.after || [])]
const toIDs = [...(item.before || []), ...(item.after || [])];
for (const id of toIDs) {
const index = indexOfGroupContainingID(groups, id, group)
if (index === -1) continue
const mergeTarget = groups[index]
const index = indexOfGroupContainingID(groups, id, group);
if (index === -1) continue;
const mergeTarget = groups[index];
mergeTarget.push(...group)
groups.splice(i, 1)
return true
mergeTarget.push(...group);
groups.splice(i, 1);
return true;
}
}
}
return false
return false;
}
function mergeGroups (groups) {
let merged = true
let merged = true;
while (merged) {
merged = attemptToMergeAGroup(groups)
merged = attemptToMergeAGroup(groups);
}
return groups
return groups;
}
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]))
const originalOrder = group.map((node, i) => i);
const edges = new Map();
const idToIndex = new Map(group.map((item, i) => [item.id, i]));
group.forEach((item, i) => {
if (item.before) {
item.before.forEach(toID => {
const to = idToIndex.get(toID)
const to = idToIndex.get(toID);
if (to != null) {
pushOntoMultiMap(edges, to, i)
pushOntoMultiMap(edges, to, i);
}
})
});
}
if (item.after) {
item.after.forEach(toID => {
const to = idToIndex.get(toID)
const to = idToIndex.get(toID);
if (to != null) {
pushOntoMultiMap(edges, i, to)
pushOntoMultiMap(edges, i, to);
}
})
});
}
})
});
const sortedNodes = sortTopologically(originalOrder, edges)
return sortedNodes.map(i => group[i])
const sortedNodes = sortTopologically(originalOrder, edges);
return sortedNodes.map(i => group[i]);
}
function findEdgesInGroup (groups, i, edges) {
const group = groups[i]
const group = groups[i];
for (const item of group) {
if (item.beforeGroupContaining) {
for (const id of item.beforeGroupContaining) {
const to = indexOfGroupContainingID(groups, id, group)
const to = indexOfGroupContainingID(groups, id, group);
if (to !== -1) {
pushOntoMultiMap(edges, to, i)
return
pushOntoMultiMap(edges, to, i);
return;
}
}
}
if (item.afterGroupContaining) {
for (const id of item.afterGroupContaining) {
const to = indexOfGroupContainingID(groups, id, group)
const to = indexOfGroupContainingID(groups, id, group);
if (to !== -1) {
pushOntoMultiMap(edges, i, to)
return
pushOntoMultiMap(edges, i, to);
return;
}
}
}
@@ -148,29 +148,29 @@ function findEdgesInGroup (groups, i, edges) {
}
function sortGroups (groups) {
const originalOrder = groups.map((item, i) => i)
const edges = new Map()
const originalOrder = groups.map((item, i) => i);
const edges = new Map();
for (let i = 0; i < groups.length; i++) {
findEdgesInGroup(groups, i, edges)
findEdgesInGroup(groups, i, edges);
}
const sortedGroupIndexes = sortTopologically(originalOrder, edges)
return sortedGroupIndexes.map(i => groups[i])
const sortedGroupIndexes = sortTopologically(originalOrder, edges);
return sortedGroupIndexes.map(i => groups[i]);
}
function sortMenuItems (menuItems) {
const isSeparator = (item) => item.type === 'separator'
const separators = menuItems.filter(i => i.type === 'separator')
const isSeparator = (item) => item.type === 'separator';
const separators = menuItems.filter(i => i.type === 'separator');
// Split the items into their implicit groups based upon separators.
const groups = splitArray(menuItems, isSeparator)
const mergedGroups = mergeGroups(groups)
const mergedGroupsWithSortedItems = mergedGroups.map(sortItemsInGroup)
const sortedGroups = sortGroups(mergedGroupsWithSortedItems)
const groups = splitArray(menuItems, isSeparator);
const mergedGroups = mergeGroups(groups);
const mergedGroupsWithSortedItems = mergedGroups.map(sortItemsInGroup);
const sortedGroups = sortGroups(mergedGroupsWithSortedItems);
const joined = joinArrays(sortedGroups, separators)
return joined
const joined = joinArrays(sortedGroups, separators);
return joined;
}
module.exports = { sortMenuItems }
module.exports = { sortMenuItems };

View File

@@ -1,16 +1,16 @@
'use strict'
'use strict';
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 { 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
let applicationMenu = null
let groupIdIndex = 0
const { Menu } = bindings;
let applicationMenu = null;
let groupIdIndex = 0;
Object.setPrototypeOf(Menu.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Menu.prototype, EventEmitter.prototype);
// Menu Delegate.
// This object should hold no reference to |Menu| to avoid cyclic reference.
@@ -20,172 +20,172 @@ const delegate = {
shouldCommandIdWorkWhenHidden: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].acceleratorWorksWhenHidden : undefined,
isCommandIdVisible: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].visible : undefined,
getAcceleratorForCommandId: (menu, id, useDefaultAccelerator) => {
const command = menu.commandsMap[id]
if (!command) return
if (command.accelerator != null) return command.accelerator
if (useDefaultAccelerator) return command.getDefaultRoleAccelerator()
const command = menu.commandsMap[id];
if (!command) return;
if (command.accelerator != null) return command.accelerator;
if (useDefaultAccelerator) return command.getDefaultRoleAccelerator();
},
shouldRegisterAcceleratorForCommandId: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].registerAccelerator : undefined,
executeCommand: (menu, event, id) => {
const command = menu.commandsMap[id]
if (!command) return
command.click(event, TopLevelWindow.getFocusedWindow(), webContents.getFocusedWebContents())
const command = menu.commandsMap[id];
if (!command) return;
command.click(event, TopLevelWindow.getFocusedWindow(), webContents.getFocusedWebContents());
},
menuWillShow: (menu) => {
// Ensure radio groups have at least one menu item selected
for (const id in menu.groupsMap) {
const found = menu.groupsMap[id].find(item => item.checked) || null
if (!found) v8Util.setHiddenValue(menu.groupsMap[id][0], 'checked', true)
for (const id of Object.keys(menu.groupsMap)) {
const found = menu.groupsMap[id].find(item => item.checked) || null;
if (!found) v8Util.setHiddenValue(menu.groupsMap[id][0], 'checked', true);
}
}
}
};
/* Instance Methods */
Menu.prototype._init = function () {
this.commandsMap = {}
this.groupsMap = {}
this.items = []
this.delegate = delegate
}
this.commandsMap = {};
this.groupsMap = {};
this.items = [];
this.delegate = delegate;
};
Menu.prototype.popup = function (options = {}) {
if (options == null || typeof options !== 'object') {
throw new TypeError('Options must be an object')
throw new TypeError('Options must be an object');
}
let { window, x, y, positioningItem, callback } = options
let { window, x, y, positioningItem, callback } = options;
// no callback passed
if (!callback || typeof callback !== 'function') callback = () => {}
if (!callback || typeof callback !== 'function') callback = () => {};
// set defaults
if (typeof x !== 'number') x = -1
if (typeof y !== 'number') y = -1
if (typeof positioningItem !== 'number') positioningItem = -1
if (typeof x !== 'number') x = -1;
if (typeof y !== 'number') y = -1;
if (typeof positioningItem !== 'number') positioningItem = -1;
// find which window to use
const wins = TopLevelWindow.getAllWindows()
const wins = TopLevelWindow.getAllWindows();
if (!wins || wins.indexOf(window) === -1) {
window = TopLevelWindow.getFocusedWindow()
window = TopLevelWindow.getFocusedWindow();
if (!window && wins && wins.length > 0) {
window = wins[0]
window = wins[0];
}
if (!window) {
throw new Error(`Cannot open Menu without a TopLevelWindow present`)
throw new Error(`Cannot open Menu without a TopLevelWindow present`);
}
}
this.popupAt(window, x, y, positioningItem, callback)
return { browserWindow: window, x, y, position: positioningItem }
}
this.popupAt(window, x, y, positioningItem, callback);
return { browserWindow: window, x, y, position: positioningItem };
};
Menu.prototype.closePopup = function (window) {
if (window instanceof TopLevelWindow) {
this.closePopupAt(window.id)
this.closePopupAt(window.id);
} else {
// Passing -1 (invalid) would make closePopupAt close the all menu runners
// belong to this menu.
this.closePopupAt(-1)
this.closePopupAt(-1);
}
}
};
Menu.prototype.getMenuItemById = function (id) {
const items = this.items
const items = this.items;
let found = items.find(item => item.id === id) || null
let found = items.find(item => item.id === id) || null;
for (let i = 0; !found && i < items.length; i++) {
if (items[i].submenu) {
found = items[i].submenu.getMenuItemById(id)
found = items[i].submenu.getMenuItemById(id);
}
}
return found
}
return found;
};
Menu.prototype.append = function (item) {
return this.insert(this.getItemCount(), item)
}
return this.insert(this.getItemCount(), item);
};
Menu.prototype.insert = function (pos, item) {
if ((item ? item.constructor : void 0) !== MenuItem) {
throw new TypeError('Invalid item')
throw new TypeError('Invalid item');
}
if (pos < 0) {
throw new RangeError(`Position ${pos} cannot be less than 0`)
throw new RangeError(`Position ${pos} cannot be less than 0`);
} else if (pos > this.getItemCount()) {
throw new RangeError(`Position ${pos} cannot be greater than the total MenuItem count`)
throw new RangeError(`Position ${pos} cannot be greater than the total MenuItem count`);
}
// insert item depending on its type
insertItemByType.call(this, item, pos)
insertItemByType.call(this, item, pos);
// set item properties
if (item.sublabel) this.setSublabel(pos, item.sublabel)
if (item.toolTip) this.setToolTip(pos, item.toolTip)
if (item.icon) this.setIcon(pos, item.icon)
if (item.role) this.setRole(pos, item.role)
if (item.sublabel) this.setSublabel(pos, item.sublabel);
if (item.toolTip) this.setToolTip(pos, item.toolTip);
if (item.icon) this.setIcon(pos, item.icon);
if (item.role) this.setRole(pos, item.role);
// Make menu accessable to items.
item.overrideReadOnlyProperty('menu', this)
item.overrideReadOnlyProperty('menu', this);
// Remember the items.
this.items.splice(pos, 0, item)
this.commandsMap[item.commandId] = item
}
this.items.splice(pos, 0, item);
this.commandsMap[item.commandId] = item;
};
Menu.prototype._callMenuWillShow = function () {
if (this.delegate) this.delegate.menuWillShow(this)
if (this.delegate) this.delegate.menuWillShow(this);
this.items.forEach(item => {
if (item.submenu) item.submenu._callMenuWillShow()
})
}
if (item.submenu) item.submenu._callMenuWillShow();
});
};
/* Static Methods */
Menu.getApplicationMenu = () => applicationMenu
Menu.getApplicationMenu = () => applicationMenu;
Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder
Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder;
// set application menu with a preexisting menu
Menu.setApplicationMenu = function (menu) {
if (menu && menu.constructor !== Menu) {
throw new TypeError('Invalid menu')
throw new TypeError('Invalid menu');
}
applicationMenu = menu
v8Util.setHiddenValue(global, 'applicationMenuSet', true)
applicationMenu = menu;
v8Util.setHiddenValue(global, 'applicationMenuSet', true);
if (process.platform === 'darwin') {
if (!menu) return
menu._callMenuWillShow()
bindings.setApplicationMenu(menu)
if (!menu) return;
menu._callMenuWillShow();
bindings.setApplicationMenu(menu);
} else {
const windows = TopLevelWindow.getAllWindows()
return windows.map(w => w.setMenu(menu))
const windows = TopLevelWindow.getAllWindows();
return windows.map(w => w.setMenu(menu));
}
}
};
Menu.buildFromTemplate = function (template) {
if (!Array.isArray(template)) {
throw new TypeError('Invalid template for Menu: Menu template must be an array')
throw new TypeError('Invalid template for Menu: Menu template must be an array');
}
if (!areValidTemplateItems(template)) {
throw new TypeError('Invalid template for MenuItem: must have at least one of label, role or type')
throw new TypeError('Invalid template for MenuItem: must have at least one of label, role or type');
}
const filtered = removeExtraSeparators(template)
const sorted = sortTemplate(filtered)
const filtered = removeExtraSeparators(template);
const sorted = sortTemplate(filtered);
const menu = new Menu()
const menu = new Menu();
sorted.forEach(item => {
if (item instanceof MenuItem) {
menu.append(item)
menu.append(item);
} else {
menu.append(new MenuItem(item))
menu.append(new MenuItem(item));
}
})
});
return menu
}
return menu;
};
/* Helper Functions */
@@ -196,51 +196,50 @@ function areValidTemplateItems (template) {
typeof item === 'object' &&
(item.hasOwnProperty('label') ||
item.hasOwnProperty('role') ||
item.type === 'separator'))
item.type === 'separator'));
}
function sortTemplate (template) {
const sorted = sortMenuItems(template)
for (const id in sorted) {
const item = sorted[id]
const sorted = sortMenuItems(template);
for (const item of sorted) {
if (Array.isArray(item.submenu)) {
item.submenu = sortTemplate(item.submenu)
item.submenu = sortTemplate(item.submenu);
}
}
return sorted
return sorted;
}
// Search between separators to find a radio menu item and return its group id
function generateGroupId (items, pos) {
if (pos > 0) {
for (let idx = pos - 1; idx >= 0; idx--) {
if (items[idx].type === 'radio') return items[idx].groupId
if (items[idx].type === 'separator') break
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].groupId
if (items[idx].type === 'separator') break
if (items[idx].type === 'radio') return items[idx].groupId;
if (items[idx].type === 'separator') break;
}
}
groupIdIndex += 1
return groupIdIndex
groupIdIndex += 1;
return groupIdIndex;
}
function removeExtraSeparators (items) {
// fold adjacent separators together
let ret = items.filter((e, idx, arr) => {
if (e.visible === false) return true
return e.type !== 'separator' || idx === 0 || arr[idx - 1].type !== 'separator'
})
if (e.visible === false) return true;
return e.type !== 'separator' || idx === 0 || arr[idx - 1].type !== 'separator';
});
// remove edge separators
ret = ret.filter((e, idx, arr) => {
if (e.visible === false) return true
return e.type !== 'separator' || (idx !== 0 && idx !== arr.length - 1)
})
if (e.visible === false) return true;
return e.type !== 'separator' || (idx !== 0 && idx !== arr.length - 1);
});
return ret
return ret;
}
function insertItemByType (item, pos) {
@@ -251,28 +250,28 @@ function insertItemByType (item, pos) {
submenu: () => this.insertSubMenu(pos, item.commandId, item.label, item.submenu),
radio: () => {
// Grouping radio menu items
item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos))
item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos));
if (this.groupsMap[item.groupId] == null) {
this.groupsMap[item.groupId] = []
this.groupsMap[item.groupId] = [];
}
this.groupsMap[item.groupId].push(item)
this.groupsMap[item.groupId].push(item);
// Setting a radio menu item should flip other items in the group.
v8Util.setHiddenValue(item, 'checked', item.checked)
v8Util.setHiddenValue(item, 'checked', item.checked);
Object.defineProperty(item, 'checked', {
enumerable: true,
get: () => v8Util.getHiddenValue(item, 'checked'),
set: () => {
this.groupsMap[item.groupId].forEach(other => {
if (other !== item) v8Util.setHiddenValue(other, 'checked', false)
})
v8Util.setHiddenValue(item, 'checked', true)
if (other !== item) v8Util.setHiddenValue(other, 'checked', false);
});
v8Util.setHiddenValue(item, 'checked', true);
}
})
this.insertRadioItem(pos, item.commandId, item.label, item.groupId)
});
this.insertRadioItem(pos, item.commandId, item.label, item.groupId);
}
}
types[item.type]()
};
types[item.type]();
}
module.exports = Menu
module.exports = Menu;

View File

@@ -1,11 +1,11 @@
'use strict'
'use strict';
// TODO: Figure out a way to not duplicate this information between here and module-list
// It is currently duplicated as module-list "require"s all the browser API file and the
// remote module in the renderer process depends on that file. As a result webpack
// includes all the browser API files in the renderer process as well and we want to avoid that
const features = process.electronBinding('features')
const features = process.electronBinding('features');
// Browser side modules, please sort alphabetically.
module.exports = [
@@ -37,7 +37,7 @@ module.exports = [
{ name: 'View' },
{ name: 'webContents' },
{ name: 'WebContentsView' }
]
];
if (features.isViewApiEnabled()) {
module.exports.push(
@@ -48,5 +48,5 @@ if (features.isViewApiEnabled()) {
{ name: 'MdTextButton' },
{ name: 'ResizeArea' },
{ name: 'TextField' }
)
);
}

View File

@@ -1,6 +1,6 @@
// TODO: Updating this file also required updating the module-keys file
const features = process.electronBinding('features')
const features = process.electronBinding('features');
// Browser side modules, please sort alphabetically.
export const browserModuleList: ElectronInternal.ModuleEntry[] = [
@@ -32,7 +32,7 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'View', loader: () => require('./view') },
{ name: 'webContents', loader: () => require('./web-contents') },
{ name: 'WebContentsView', loader: () => require('./web-contents-view') }
]
];
if (features.isViewApiEnabled()) {
browserModuleList.push(
@@ -43,5 +43,5 @@ if (features.isViewApiEnabled()) {
{ name: 'MdTextButton', loader: () => require('./views/md-text-button') },
{ name: 'ResizeArea', loader: () => require('./views/resize-area') },
{ name: 'TextField', loader: () => require('./views/text-field') }
)
);
}

View File

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

View File

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

View File

@@ -1,16 +1,16 @@
'use strict'
'use strict';
const url = require('url')
const { EventEmitter } = require('events')
const { Readable, Writable } = require('stream')
const { app } = require('electron')
const { Session } = process.electronBinding('session')
const { net, Net, _isValidHeaderName, _isValidHeaderValue } = process.electronBinding('net')
const { URLLoader } = net
const url = require('url');
const { EventEmitter } = require('events');
const { Readable, Writable } = require('stream');
const { app } = require('electron');
const { Session } = process.electronBinding('session');
const { net, Net, _isValidHeaderName, _isValidHeaderValue } = process.electronBinding('net');
const { URLLoader } = net;
Object.setPrototypeOf(URLLoader.prototype, EventEmitter.prototype)
Object.setPrototypeOf(URLLoader.prototype, EventEmitter.prototype);
const kSupportedProtocols = new Set(['http:', 'https:'])
const kSupportedProtocols = new Set(['http:', 'https:']);
// set of headers that Node.js discards duplicates for
// see https://nodejs.org/api/http.html#http_message_headers
@@ -33,27 +33,27 @@ const discardableDuplicateHeaders = new Set([
'server',
'age',
'expires'
])
]);
class IncomingMessage extends Readable {
constructor (responseHead) {
super()
this._shouldPush = false
this._data = []
this._responseHead = responseHead
super();
this._shouldPush = false;
this._data = [];
this._responseHead = responseHead;
}
get statusCode () {
return this._responseHead.statusCode
return this._responseHead.statusCode;
}
get statusMessage () {
return this._responseHead.statusMessage
return this._responseHead.statusMessage;
}
get headers () {
const filteredHeaders = {}
const { rawHeaders } = this._responseHead
const filteredHeaders = {};
const { rawHeaders } = this._responseHead;
rawHeaders.forEach(header => {
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key) &&
discardableDuplicateHeaders.has(header.key)) {
@@ -63,145 +63,145 @@ class IncomingMessage extends Readable {
// keep set-cookie as an array per Node.js rules
// see https://nodejs.org/api/http.html#http_message_headers
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
filteredHeaders[header.key].push(header.value)
filteredHeaders[header.key].push(header.value);
} else {
filteredHeaders[header.key] = [header.value]
filteredHeaders[header.key] = [header.value];
}
} else {
// for non-cookie headers, the values are joined together with ', '
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
filteredHeaders[header.key] += `, ${header.value}`
filteredHeaders[header.key] += `, ${header.value}`;
} else {
filteredHeaders[header.key] = header.value
filteredHeaders[header.key] = header.value;
}
}
}
})
return filteredHeaders
});
return filteredHeaders;
}
get httpVersion () {
return `${this.httpVersionMajor}.${this.httpVersionMinor}`
return `${this.httpVersionMajor}.${this.httpVersionMinor}`;
}
get httpVersionMajor () {
return this._responseHead.httpVersion.major
return this._responseHead.httpVersion.major;
}
get httpVersionMinor () {
return this._responseHead.httpVersion.minor
return this._responseHead.httpVersion.minor;
}
get rawTrailers () {
throw new Error('HTTP trailers are not supported')
throw new Error('HTTP trailers are not supported');
}
get trailers () {
throw new Error('HTTP trailers are not supported')
throw new Error('HTTP trailers are not supported');
}
_storeInternalData (chunk) {
this._data.push(chunk)
this._pushInternalData()
this._data.push(chunk);
this._pushInternalData();
}
_pushInternalData () {
while (this._shouldPush && this._data.length > 0) {
const chunk = this._data.shift()
this._shouldPush = this.push(chunk)
const chunk = this._data.shift();
this._shouldPush = this.push(chunk);
}
}
_read () {
this._shouldPush = true
this._pushInternalData()
this._shouldPush = true;
this._pushInternalData();
}
}
/** Writable stream that buffers up everything written to it. */
class SlurpStream extends Writable {
constructor () {
super()
this._data = Buffer.alloc(0)
super();
this._data = Buffer.alloc(0);
}
_write (chunk, encoding, callback) {
this._data = Buffer.concat([this._data, chunk])
callback()
this._data = Buffer.concat([this._data, chunk]);
callback();
}
data () { return this._data }
data () { return this._data; }
}
class ChunkedBodyStream extends Writable {
constructor (clientRequest) {
super()
this._clientRequest = clientRequest
super();
this._clientRequest = clientRequest;
}
_write (chunk, encoding, callback) {
if (this._downstream) {
this._downstream.write(chunk).then(callback, callback)
this._downstream.write(chunk).then(callback, callback);
} else {
// the contract of _write is that we won't be called again until we call
// the callback, so we're good to just save a single chunk.
this._pendingChunk = chunk
this._pendingCallback = callback
this._pendingChunk = chunk;
this._pendingCallback = callback;
// The first write to a chunked body stream begins the request.
this._clientRequest._startRequest()
this._clientRequest._startRequest();
}
}
_final (callback) {
this._downstream.done()
callback()
this._downstream.done();
callback();
}
startReading (pipe) {
if (this._downstream) {
throw new Error('two startReading calls???')
throw new Error('two startReading calls???');
}
this._downstream = pipe
this._downstream = pipe;
if (this._pendingChunk) {
const doneWriting = (maybeError) => {
const cb = this._pendingCallback
delete this._pendingCallback
delete this._pendingChunk
cb(maybeError)
}
this._downstream.write(this._pendingChunk).then(doneWriting, doneWriting)
const cb = this._pendingCallback;
delete this._pendingCallback;
delete this._pendingChunk;
cb(maybeError);
};
this._downstream.write(this._pendingChunk).then(doneWriting, doneWriting);
}
}
}
function parseOptions (options) {
if (typeof options === 'string') {
options = url.parse(options)
options = url.parse(options);
} else {
options = { ...options }
options = { ...options };
}
const method = (options.method || 'GET').toUpperCase()
let urlStr = options.url
const method = (options.method || 'GET').toUpperCase();
let urlStr = options.url;
if (!urlStr) {
const urlObj = {}
const protocol = options.protocol || 'http:'
const urlObj = {};
const protocol = options.protocol || 'http:';
if (!kSupportedProtocols.has(protocol)) {
throw new Error('Protocol "' + protocol + '" not supported')
throw new Error('Protocol "' + protocol + '" not supported');
}
urlObj.protocol = protocol
urlObj.protocol = protocol;
if (options.host) {
urlObj.host = options.host
urlObj.host = options.host;
} else {
if (options.hostname) {
urlObj.hostname = options.hostname
urlObj.hostname = options.hostname;
} else {
urlObj.hostname = 'localhost'
urlObj.hostname = 'localhost';
}
if (options.port) {
urlObj.port = options.port
urlObj.port = options.port;
}
}
@@ -212,203 +212,204 @@ function parseOptions (options) {
// well, and b) possibly too restrictive for real-world usage. That's
// why it only scans for spaces because those are guaranteed to create
// an invalid request.
throw new TypeError('Request path contains unescaped characters')
throw new TypeError('Request path contains unescaped characters');
}
const pathObj = url.parse(options.path || '/')
urlObj.pathname = pathObj.pathname
urlObj.search = pathObj.search
urlObj.hash = pathObj.hash
urlStr = url.format(urlObj)
const pathObj = url.parse(options.path || '/');
urlObj.pathname = pathObj.pathname;
urlObj.search = pathObj.search;
urlObj.hash = pathObj.hash;
urlStr = url.format(urlObj);
}
const redirectPolicy = options.redirect || 'follow'
const redirectPolicy = options.redirect || 'follow';
if (!['follow', 'error', 'manual'].includes(redirectPolicy)) {
throw new Error('redirect mode should be one of follow, error or manual')
throw new Error('redirect mode should be one of follow, error or manual');
}
if (options.headers != null && typeof options.headers !== 'object') {
throw new TypeError('headers must be an object')
throw new TypeError('headers must be an object');
}
const urlLoaderOptions = {
method: method,
url: urlStr,
redirectPolicy,
extraHeaders: options.headers || {}
}
extraHeaders: options.headers || {},
useSessionCookies: options.useSessionCookies || false
};
for (const [name, value] of Object.entries(urlLoaderOptions.extraHeaders)) {
if (!_isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${name}'`)
throw new Error(`Invalid header name: '${name}'`);
}
if (!_isValidHeaderValue(value.toString())) {
throw new Error(`Invalid value for header '${name}': '${value}'`)
throw new Error(`Invalid value for header '${name}': '${value}'`);
}
}
if (options.session) {
if (options.session instanceof Session) {
urlLoaderOptions.session = options.session
urlLoaderOptions.session = options.session;
} else {
throw new TypeError('`session` should be an instance of the Session class')
throw new TypeError('`session` should be an instance of the Session class');
}
} else if (options.partition) {
if (typeof options.partition === 'string') {
urlLoaderOptions.partition = options.partition
urlLoaderOptions.partition = options.partition;
} else {
throw new TypeError('`partition` should be a string')
throw new TypeError('`partition` should be a string');
}
}
return urlLoaderOptions
return urlLoaderOptions;
}
class ClientRequest extends Writable {
constructor (options, callback) {
super({ autoDestroy: true })
super({ autoDestroy: true });
if (!app.isReady()) {
throw new Error('net module can only be used after app is ready')
throw new Error('net module can only be used after app is ready');
}
if (callback) {
this.once('response', callback)
this.once('response', callback);
}
const { redirectPolicy, ...urlLoaderOptions } = parseOptions(options)
this._urlLoaderOptions = urlLoaderOptions
this._redirectPolicy = redirectPolicy
this._started = false
const { redirectPolicy, ...urlLoaderOptions } = parseOptions(options);
this._urlLoaderOptions = urlLoaderOptions;
this._redirectPolicy = redirectPolicy;
this._started = false;
}
set chunkedEncoding (value) {
if (this._started) {
throw new Error('chunkedEncoding can only be set before the request is started')
throw new Error('chunkedEncoding can only be set before the request is started');
}
if (typeof this._chunkedEncoding !== 'undefined') {
throw new Error('chunkedEncoding can only be set once')
throw new Error('chunkedEncoding can only be set once');
}
this._chunkedEncoding = !!value
this._chunkedEncoding = !!value;
if (this._chunkedEncoding) {
this._body = new ChunkedBodyStream(this)
this._body = new ChunkedBodyStream(this);
this._urlLoaderOptions.body = (pipe) => {
this._body.startReading(pipe)
}
this._body.startReading(pipe);
};
}
}
setHeader (name, value) {
if (typeof name !== 'string') {
throw new TypeError('`name` should be a string in setHeader(name, value)')
throw new TypeError('`name` should be a string in setHeader(name, value)');
}
if (value == null) {
throw new Error('`value` required in setHeader("' + name + '", value)')
throw new Error('`value` required in setHeader("' + name + '", value)');
}
if (this._started || this._firstWrite) {
throw new Error('Can\'t set headers after they are sent')
throw new Error('Can\'t set headers after they are sent');
}
if (!_isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${name}'`)
throw new Error(`Invalid header name: '${name}'`);
}
if (!_isValidHeaderValue(value.toString())) {
throw new Error(`Invalid value for header '${name}': '${value}'`)
throw new Error(`Invalid value for header '${name}': '${value}'`);
}
const key = name.toLowerCase()
this._urlLoaderOptions.extraHeaders[key] = value
const key = name.toLowerCase();
this._urlLoaderOptions.extraHeaders[key] = value;
}
getHeader (name) {
if (name == null) {
throw new Error('`name` is required for getHeader(name)')
throw new Error('`name` is required for getHeader(name)');
}
const key = name.toLowerCase()
return this._urlLoaderOptions.extraHeaders[key]
const key = name.toLowerCase();
return this._urlLoaderOptions.extraHeaders[key];
}
removeHeader (name) {
if (name == null) {
throw new Error('`name` is required for removeHeader(name)')
throw new Error('`name` is required for removeHeader(name)');
}
if (this._started || this._firstWrite) {
throw new Error('Can\'t remove headers after they are sent')
throw new Error('Can\'t remove headers after they are sent');
}
const key = name.toLowerCase()
delete this._urlLoaderOptions.extraHeaders[key]
const key = name.toLowerCase();
delete this._urlLoaderOptions.extraHeaders[key];
}
_write (chunk, encoding, callback) {
this._firstWrite = true
this._firstWrite = true;
if (!this._body) {
this._body = new SlurpStream()
this._body = new SlurpStream();
this._body.on('finish', () => {
this._urlLoaderOptions.body = this._body.data()
this._startRequest()
})
this._urlLoaderOptions.body = this._body.data();
this._startRequest();
});
}
// TODO: is this the right way to forward to another stream?
this._body.write(chunk, encoding, callback)
this._body.write(chunk, encoding, callback);
}
_final (callback) {
if (this._body) {
// TODO: is this the right way to forward to another stream?
this._body.end(callback)
this._body.end(callback);
} else {
// end() called without a body, go ahead and start the request
this._startRequest()
callback()
this._startRequest();
callback();
}
}
_startRequest () {
this._started = true
this._started = true;
const stringifyValues = (obj) => {
const ret = {}
for (const k in obj) {
ret[k] = obj[k].toString()
const ret = {};
for (const k of Object.keys(obj)) {
ret[k] = obj[k].toString();
}
return ret
}
const opts = { ...this._urlLoaderOptions, extraHeaders: stringifyValues(this._urlLoaderOptions.extraHeaders) }
this._urlLoader = new URLLoader(opts)
return ret;
};
const opts = { ...this._urlLoaderOptions, extraHeaders: stringifyValues(this._urlLoaderOptions.extraHeaders) };
this._urlLoader = new URLLoader(opts);
this._urlLoader.on('response-started', (event, finalUrl, responseHead) => {
const response = this._response = new IncomingMessage(responseHead)
this.emit('response', response)
})
const response = this._response = new IncomingMessage(responseHead);
this.emit('response', response);
});
this._urlLoader.on('data', (event, data) => {
this._response._storeInternalData(Buffer.from(data))
})
this._response._storeInternalData(Buffer.from(data));
});
this._urlLoader.on('complete', () => {
if (this._response) { this._response._storeInternalData(null) }
})
if (this._response) { this._response._storeInternalData(null); }
});
this._urlLoader.on('error', (event, netErrorString) => {
const error = new Error(netErrorString)
if (this._response) this._response.destroy(error)
this._die(error)
})
const error = new Error(netErrorString);
if (this._response) this._response.destroy(error);
this._die(error);
});
this._urlLoader.on('login', (event, authInfo, callback) => {
const handled = this.emit('login', authInfo, callback)
const handled = this.emit('login', authInfo, callback);
if (!handled) {
// If there were no listeners, cancel the authentication request.
callback()
callback();
}
})
});
this._urlLoader.on('redirect', (event, redirectInfo, headers) => {
const { statusCode, newMethod, newUrl } = redirectInfo
const { statusCode, newMethod, newUrl } = redirectInfo;
if (this._redirectPolicy === 'error') {
this._die(new Error(`Attempted to redirect, but redirect policy was 'error'`))
this._die(new Error(`Attempted to redirect, but redirect policy was 'error'`));
} else if (this._redirectPolicy === 'manual') {
let _followRedirect = false
this._followRedirectCb = () => { _followRedirect = true }
let _followRedirect = false;
this._followRedirectCb = () => { _followRedirect = true; };
try {
this.emit('redirect', statusCode, newMethod, newUrl, headers)
this.emit('redirect', statusCode, newMethod, newUrl, headers);
} finally {
this._followRedirectCb = null
this._followRedirectCb = null;
if (!_followRedirect && !this._aborted) {
this._die(new Error('Redirect was cancelled'))
this._die(new Error('Redirect was cancelled'));
}
}
} else if (this._redirectPolicy === 'follow') {
@@ -416,61 +417,61 @@ class ClientRequest extends Writable {
// allowed but does nothing. (Perhaps it should throw an error
// though...? Since the redirect will happen regardless.)
try {
this._followRedirectCb = () => {}
this.emit('redirect', statusCode, newMethod, newUrl, headers)
this._followRedirectCb = () => {};
this.emit('redirect', statusCode, newMethod, newUrl, headers);
} finally {
this._followRedirectCb = null
this._followRedirectCb = null;
}
} else {
this._die(new Error(`Unexpected redirect policy '${this._redirectPolicy}'`))
this._die(new Error(`Unexpected redirect policy '${this._redirectPolicy}'`));
}
})
});
this._urlLoader.on('upload-progress', (event, position, total) => {
this._uploadProgress = { active: true, started: true, current: position, total }
this.emit('upload-progress', position, total) // Undocumented, for now
})
this._uploadProgress = { active: true, started: true, current: position, total };
this.emit('upload-progress', position, total); // Undocumented, for now
});
this._urlLoader.on('download-progress', (event, current) => {
if (this._response) {
this._response.emit('download-progress', current) // Undocumented, for now
this._response.emit('download-progress', current); // Undocumented, for now
}
})
});
}
followRedirect () {
if (this._followRedirectCb) {
this._followRedirectCb()
this._followRedirectCb();
} else {
throw new Error('followRedirect() called, but was not waiting for a redirect')
throw new Error('followRedirect() called, but was not waiting for a redirect');
}
}
abort () {
if (!this._aborted) {
process.nextTick(() => { this.emit('abort') })
process.nextTick(() => { this.emit('abort'); });
}
this._aborted = true
this._die()
this._aborted = true;
this._die();
}
_die (err) {
this.destroy(err)
this.destroy(err);
if (this._urlLoader) {
this._urlLoader.cancel()
if (this._response) this._response.destroy(err)
this._urlLoader.cancel();
if (this._response) this._response.destroy(err);
}
}
getUploadProgress () {
return this._uploadProgress ? { ...this._uploadProgress } : { active: false }
return this._uploadProgress ? { ...this._uploadProgress } : { active: false };
}
}
Net.prototype.request = function (options, callback) {
return new ClientRequest(options, callback)
}
return new ClientRequest(options, callback);
};
net.ClientRequest = ClientRequest
net.ClientRequest = ClientRequest;
module.exports = net
module.exports = net;

View File

@@ -1,10 +1,10 @@
'use strict'
'use strict';
const { EventEmitter } = require('events')
const { Notification, isSupported } = process.electronBinding('notification')
const { EventEmitter } = require('events');
const { Notification, isSupported } = process.electronBinding('notification');
Object.setPrototypeOf(Notification.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Notification.prototype, EventEmitter.prototype);
Notification.isSupported = isSupported
Notification.isSupported = isSupported;
module.exports = Notification
module.exports = Notification;

View File

@@ -1,14 +1,14 @@
'use strict'
'use strict';
import { createLazyInstance } from '../utils'
import { createLazyInstance } from '../utils';
const { EventEmitter } = require('events')
const { createPowerMonitor, PowerMonitor } = process.electronBinding('power_monitor')
const { EventEmitter } = require('events');
const { createPowerMonitor, PowerMonitor } = process.electronBinding('power_monitor');
// PowerMonitor is an EventEmitter.
Object.setPrototypeOf(PowerMonitor.prototype, EventEmitter.prototype)
Object.setPrototypeOf(PowerMonitor.prototype, EventEmitter.prototype);
const powerMonitor = createLazyInstance(createPowerMonitor, PowerMonitor, true)
const powerMonitor = createLazyInstance(createPowerMonitor, PowerMonitor, true);
if (process.platform === 'linux') {
// In order to delay system shutdown when e.preventDefault() is invoked
@@ -18,21 +18,21 @@ if (process.platform === 'linux') {
//
// So here we watch for 'shutdown' listeners to be added or removed and
// set or unset our shutdown delay lock accordingly.
const { app } = require('electron')
const { app } = require('electron');
app.whenReady().then(() => {
powerMonitor.on('newListener', (event: string) => {
// whenever the listener count is incremented to one...
if (event === 'shutdown' && powerMonitor.listenerCount('shutdown') === 0) {
powerMonitor.blockShutdown()
powerMonitor.blockShutdown();
}
})
});
powerMonitor.on('removeListener', (event: string) => {
// whenever the listener count is decremented to zero...
if (event === 'shutdown' && powerMonitor.listenerCount('shutdown') === 0) {
powerMonitor.unblockShutdown()
powerMonitor.unblockShutdown();
}
})
})
});
});
}
module.exports = powerMonitor
module.exports = powerMonitor;

View File

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

View File

@@ -1,29 +1,29 @@
import { app, session } from 'electron'
import { app, session } from 'electron';
// Global protocol APIs.
const protocol = process.electronBinding('protocol')
const protocol = process.electronBinding('protocol');
// Fallback protocol APIs of default session.
Object.setPrototypeOf(protocol, new Proxy({}, {
get (_target, property) {
if (!app.isReady()) return
if (!app.isReady()) return;
const protocol = session.defaultSession!.protocol
if (!Object.getPrototypeOf(protocol).hasOwnProperty(property)) return
const protocol = session.defaultSession!.protocol;
if (!Object.getPrototypeOf(protocol).hasOwnProperty(property)) return;
// Returning a native function directly would throw error.
return (...args: any[]) => (protocol[property as keyof Electron.Protocol] as Function)(...args)
return (...args: any[]) => (protocol[property as keyof Electron.Protocol] as Function)(...args);
},
ownKeys () {
if (!app.isReady()) return []
if (!app.isReady()) return [];
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession!.protocol))
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession!.protocol));
},
getOwnPropertyDescriptor () {
return { configurable: true, enumerable: true }
return { configurable: true, enumerable: true };
}
}))
}));
export default protocol
export default protocol;

View File

@@ -1,10 +1,10 @@
'use strict'
'use strict';
import { createLazyInstance } from '../utils'
const { EventEmitter } = require('events')
const { Screen, createScreen } = process.electronBinding('screen')
import { createLazyInstance } from '../utils';
const { EventEmitter } = require('events');
const { Screen, createScreen } = process.electronBinding('screen');
// Screen is an EventEmitter.
Object.setPrototypeOf(Screen.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Screen.prototype, EventEmitter.prototype);
module.exports = createLazyInstance(createScreen, Screen, true)
module.exports = createLazyInstance(createScreen, Screen, true);

View File

@@ -1,54 +1,54 @@
'use strict'
'use strict';
const { EventEmitter } = require('events')
const { app, deprecate } = require('electron')
const { fromPartition, Session, Cookies, NetLog, Protocol, ServiceWorkerContext } = process.electronBinding('session')
const { EventEmitter } = require('events');
const { app, deprecate } = require('electron');
const { fromPartition, Session, Cookies, NetLog, Protocol, ServiceWorkerContext } = process.electronBinding('session');
// Public API.
Object.defineProperties(exports, {
defaultSession: {
enumerable: true,
get () { return fromPartition('') }
get () { return fromPartition(''); }
},
fromPartition: {
enumerable: true,
value: fromPartition
}
})
});
Object.setPrototypeOf(Cookies.prototype, EventEmitter.prototype)
Object.setPrototypeOf(ServiceWorkerContext.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Session.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Cookies.prototype, EventEmitter.prototype);
Object.setPrototypeOf(ServiceWorkerContext.prototype, EventEmitter.prototype);
Object.setPrototypeOf(Session.prototype, EventEmitter.prototype);
Session.prototype._init = function () {
app.emit('session-created', this)
}
app.emit('session-created', this);
};
const _originalStartLogging = NetLog.prototype.startLogging
const _originalStartLogging = NetLog.prototype.startLogging;
NetLog.prototype.startLogging = function (path, ...args) {
this._currentlyLoggingPath = path
this._currentlyLoggingPath = path;
try {
return _originalStartLogging.call(this, path, ...args)
return _originalStartLogging.call(this, path, ...args);
} catch (e) {
this._currentlyLoggingPath = null
throw e
this._currentlyLoggingPath = null;
throw e;
}
}
};
const _originalStopLogging = NetLog.prototype.stopLogging
const _originalStopLogging = NetLog.prototype.stopLogging;
NetLog.prototype.stopLogging = function () {
const logPath = this._currentlyLoggingPath
this._currentlyLoggingPath = null
return _originalStopLogging.call(this).then(() => logPath)
}
const logPath = this._currentlyLoggingPath;
this._currentlyLoggingPath = null;
return _originalStopLogging.call(this).then(() => logPath);
};
const currentlyLoggingPathDeprecated = deprecate.warnOnce('currentlyLoggingPath')
const currentlyLoggingPathDeprecated = deprecate.warnOnce('currentlyLoggingPath');
Object.defineProperties(NetLog.prototype, {
currentlyLoggingPath: {
enumerable: true,
get () {
currentlyLoggingPathDeprecated()
return this._currentlyLoggingPath == null ? '' : this._currentlyLoggingPath
currentlyLoggingPathDeprecated();
return this._currentlyLoggingPath == null ? '' : this._currentlyLoggingPath;
}
}
})
});

View File

@@ -1,42 +1,41 @@
import { EventEmitter } from 'events'
import { deprecate } from 'electron'
const { systemPreferences, SystemPreferences } = process.electronBinding('system_preferences')
import { EventEmitter } from 'events';
import { deprecate } from 'electron';
const { systemPreferences, SystemPreferences } = process.electronBinding('system_preferences');
// SystemPreferences is an EventEmitter.
Object.setPrototypeOf(SystemPreferences.prototype, EventEmitter.prototype)
EventEmitter.call(systemPreferences)
Object.setPrototypeOf(SystemPreferences.prototype, EventEmitter.prototype);
EventEmitter.call(systemPreferences);
if ('appLevelAppearance' in systemPreferences) {
deprecate.fnToProperty(
SystemPreferences.prototype,
'appLevelAppearance',
'_getAppLevelAppearance',
'_setAppLevelAppearance'
)
if ('getAppLevelAppearance' in systemPreferences) {
const nativeALAGetter = systemPreferences.getAppLevelAppearance;
const nativeALASetter = systemPreferences.setAppLevelAppearance;
Object.defineProperty(SystemPreferences.prototype, 'appLevelAppearance', {
get: () => nativeALAGetter.call(systemPreferences),
set: (appearance) => nativeALASetter.call(systemPreferences, appearance)
});
}
if ('effectiveAppearance' in systemPreferences) {
deprecate.fnToProperty(
SystemPreferences.prototype,
'effectiveAppearance',
'_getEffectiveAppearance'
)
if ('getEffectiveAppearance' in systemPreferences) {
const nativeEAGetter = systemPreferences.getAppLevelAppearance;
Object.defineProperty(SystemPreferences.prototype, 'effectiveAppearance', {
get: () => nativeEAGetter.call(systemPreferences)
});
}
SystemPreferences.prototype.isDarkMode = deprecate.moveAPI(
SystemPreferences.prototype.isDarkMode,
'systemPreferences.isDarkMode()',
'nativeTheme.shouldUseDarkColors'
)
);
SystemPreferences.prototype.isInvertedColorScheme = deprecate.moveAPI(
SystemPreferences.prototype.isInvertedColorScheme,
'systemPreferences.isInvertedColorScheme()',
'nativeTheme.shouldUseInvertedColorScheme'
)
);
SystemPreferences.prototype.isHighContrastColorScheme = deprecate.moveAPI(
SystemPreferences.prototype.isHighContrastColorScheme,
'systemPreferences.isHighContrastColorScheme()',
'nativeTheme.shouldUseHighContrastColors'
)
);
module.exports = systemPreferences
module.exports = systemPreferences;

View File

@@ -1,24 +1,24 @@
'use strict'
'use strict';
const electron = require('electron')
const { EventEmitter } = require('events')
const { TopLevelWindow } = process.electronBinding('top_level_window')
const electron = require('electron');
const { EventEmitter } = require('events');
const { TopLevelWindow } = process.electronBinding('top_level_window');
Object.setPrototypeOf(TopLevelWindow.prototype, EventEmitter.prototype)
Object.setPrototypeOf(TopLevelWindow.prototype, EventEmitter.prototype);
TopLevelWindow.prototype._init = function () {
// Avoid recursive require.
const { app } = electron
const { app } = electron;
// Simulate the application menu on platforms other than macOS.
if (process.platform !== 'darwin') {
const menu = app.applicationMenu
if (menu) this.setMenu(menu)
const menu = app.applicationMenu;
if (menu) this.setMenu(menu);
}
}
};
TopLevelWindow.getFocusedWindow = () => {
return TopLevelWindow.getAllWindows().find((win) => win.isFocused())
}
return TopLevelWindow.getAllWindows().find((win) => win.isFocused());
};
module.exports = TopLevelWindow
module.exports = TopLevelWindow;

View File

@@ -1,337 +1,349 @@
'use strict'
'use strict';
const { EventEmitter } = require('events')
const { EventEmitter } = require('events');
let nextItemID = 1
let nextItemID = 1;
class TouchBar extends EventEmitter {
// Bind a touch bar to a window
static _setOnWindow (touchBar, window) {
if (window._touchBar != null) {
window._touchBar._removeFromWindow(window)
window._touchBar._removeFromWindow(window);
}
if (touchBar == null) {
window._setTouchBarItems([])
return
window._setTouchBarItems([]);
return;
}
if (Array.isArray(touchBar)) {
touchBar = new TouchBar(touchBar)
touchBar = new TouchBar(touchBar);
}
touchBar._addToWindow(window)
touchBar._addToWindow(window);
}
constructor (options) {
super()
super();
if (options == null) {
throw new Error('Must specify options object as first argument')
throw new Error('Must specify options object as first argument');
}
let { items, escapeItem } = options
let { items, escapeItem } = options;
if (!Array.isArray(items)) {
items = []
items = [];
}
this.changeListener = (item) => {
this.emit('change', item.id, item.type)
}
this.emit('change', item.id, item.type);
};
this.windowListeners = {}
this.items = {}
this.ordereredItems = []
this.escapeItem = escapeItem
this.windowListeners = {};
this.items = {};
this.ordereredItems = [];
this.escapeItem = escapeItem;
const registerItem = (item) => {
this.items[item.id] = item
item.on('change', this.changeListener)
this.items[item.id] = item;
item.on('change', this.changeListener);
if (item.child instanceof TouchBar) {
item.child.ordereredItems.forEach(registerItem)
item.child.ordereredItems.forEach(registerItem);
}
}
};
const idSet = new Set();
items.forEach((item) => {
if (!(item instanceof TouchBarItem)) {
throw new Error('Each item must be an instance of TouchBarItem')
throw new Error('Each item must be an instance of TouchBarItem');
}
this.ordereredItems.push(item)
registerItem(item)
})
if (!idSet.has(item.id)) {
idSet.add(item.id);
} else {
throw new Error('Cannot add a single instance of TouchBarItem multiple times in a TouchBar');
}
});
// register in separate loop after all items are validated
for (const item of items) {
this.ordereredItems.push(item);
registerItem(item);
}
}
set escapeItem (item) {
if (item != null && !(item instanceof TouchBarItem)) {
throw new Error('Escape item must be an instance of TouchBarItem')
throw new Error('Escape item must be an instance of TouchBarItem');
}
if (this.escapeItem != null) {
this.escapeItem.removeListener('change', this.changeListener)
this.escapeItem.removeListener('change', this.changeListener);
}
this._escapeItem = item
this._escapeItem = item;
if (this.escapeItem != null) {
this.escapeItem.on('change', this.changeListener)
this.escapeItem.on('change', this.changeListener);
}
this.emit('escape-item-change', item)
this.emit('escape-item-change', item);
}
get escapeItem () {
return this._escapeItem
return this._escapeItem;
}
_addToWindow (window) {
const { id } = window
const { id } = window;
// Already added to window
if (this.windowListeners.hasOwnProperty(id)) return
if (this.windowListeners.hasOwnProperty(id)) return;
window._touchBar = this
window._touchBar = this;
const changeListener = (itemID) => {
window._refreshTouchBarItem(itemID)
}
this.on('change', changeListener)
window._refreshTouchBarItem(itemID);
};
this.on('change', changeListener);
const escapeItemListener = (item) => {
window._setEscapeTouchBarItem(item != null ? item : {})
}
this.on('escape-item-change', escapeItemListener)
window._setEscapeTouchBarItem(item != null ? item : {});
};
this.on('escape-item-change', escapeItemListener);
const interactionListener = (event, itemID, details) => {
let item = this.items[itemID]
let item = this.items[itemID];
if (item == null && this.escapeItem != null && this.escapeItem.id === itemID) {
item = this.escapeItem
item = this.escapeItem;
}
if (item != null && item.onInteraction != null) {
item.onInteraction(details)
item.onInteraction(details);
}
}
window.on('-touch-bar-interaction', interactionListener)
};
window.on('-touch-bar-interaction', interactionListener);
const removeListeners = () => {
this.removeListener('change', changeListener)
this.removeListener('escape-item-change', escapeItemListener)
window.removeListener('-touch-bar-interaction', interactionListener)
window.removeListener('closed', removeListeners)
window._touchBar = null
delete this.windowListeners[id]
this.removeListener('change', changeListener);
this.removeListener('escape-item-change', escapeItemListener);
window.removeListener('-touch-bar-interaction', interactionListener);
window.removeListener('closed', removeListeners);
window._touchBar = null;
delete this.windowListeners[id];
const unregisterItems = (items) => {
for (const item of items) {
item.removeListener('change', this.changeListener)
item.removeListener('change', this.changeListener);
if (item.child instanceof TouchBar) {
unregisterItems(item.child.ordereredItems)
unregisterItems(item.child.ordereredItems);
}
}
}
unregisterItems(this.ordereredItems)
};
unregisterItems(this.ordereredItems);
if (this.escapeItem) {
this.escapeItem.removeListener('change', this.changeListener)
this.escapeItem.removeListener('change', this.changeListener);
}
}
window.once('closed', removeListeners)
this.windowListeners[id] = removeListeners
};
window.once('closed', removeListeners);
this.windowListeners[id] = removeListeners;
window._setTouchBarItems(this.ordereredItems)
escapeItemListener(this.escapeItem)
window._setTouchBarItems(this.ordereredItems);
escapeItemListener(this.escapeItem);
}
_removeFromWindow (window) {
const removeListeners = this.windowListeners[window.id]
if (removeListeners != null) removeListeners()
const removeListeners = this.windowListeners[window.id];
if (removeListeners != null) removeListeners();
}
}
class TouchBarItem extends EventEmitter {
constructor () {
super()
this._addImmutableProperty('id', `${nextItemID++}`)
this._parents = []
super();
this._addImmutableProperty('id', `${nextItemID++}`);
this._parents = [];
}
_addImmutableProperty (name, value) {
Object.defineProperty(this, name, {
get: function () {
return value
return value;
},
set: function () {
throw new Error(`Cannot override property ${name}`)
throw new Error(`Cannot override property ${name}`);
},
enumerable: true,
configurable: false
})
});
}
_addLiveProperty (name, initialValue) {
const privateName = `_${name}`
this[privateName] = initialValue
const privateName = `_${name}`;
this[privateName] = initialValue;
Object.defineProperty(this, name, {
get: function () {
return this[privateName]
return this[privateName];
},
set: function (value) {
this[privateName] = value
this.emit('change', this)
this[privateName] = value;
this.emit('change', this);
},
enumerable: true
})
});
}
_addParent (item) {
const existing = this._parents.some(test => test.id === item.id)
const existing = this._parents.some(test => test.id === item.id);
if (!existing) {
this._parents.push({
id: item.id,
type: item.type
})
});
}
}
}
TouchBar.TouchBarButton = class TouchBarButton extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'button')
this._addLiveProperty('label', config.label)
this._addLiveProperty('accessibilityLabel', config.accessibilityLabel)
this._addLiveProperty('backgroundColor', config.backgroundColor)
this._addLiveProperty('icon', config.icon)
this._addLiveProperty('iconPosition', config.iconPosition)
this._addLiveProperty('enabled', typeof config.enabled !== 'boolean' ? true : config.enabled)
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'button');
this._addLiveProperty('label', config.label);
this._addLiveProperty('accessibilityLabel', config.accessibilityLabel);
this._addLiveProperty('backgroundColor', config.backgroundColor);
this._addLiveProperty('icon', config.icon);
this._addLiveProperty('iconPosition', config.iconPosition);
this._addLiveProperty('enabled', typeof config.enabled !== 'boolean' ? true : config.enabled);
if (typeof config.click === 'function') {
this._addImmutableProperty('onInteraction', () => {
config.click()
})
config.click();
});
}
}
}
};
TouchBar.TouchBarColorPicker = class TouchBarColorPicker extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'colorpicker')
this._addLiveProperty('availableColors', config.availableColors)
this._addLiveProperty('selectedColor', config.selectedColor)
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'colorpicker');
this._addLiveProperty('availableColors', config.availableColors);
this._addLiveProperty('selectedColor', config.selectedColor);
if (typeof config.change === 'function') {
this._addImmutableProperty('onInteraction', (details) => {
this._selectedColor = details.color
config.change(details.color)
})
this._selectedColor = details.color;
config.change(details.color);
});
}
}
}
};
TouchBar.TouchBarGroup = class TouchBarGroup extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'group')
const defaultChild = (config.items instanceof TouchBar) ? config.items : new TouchBar(config.items)
this._addLiveProperty('child', defaultChild)
this.child.ordereredItems.forEach((item) => item._addParent(this))
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'group');
const defaultChild = (config.items instanceof TouchBar) ? config.items : new TouchBar(config.items);
this._addLiveProperty('child', defaultChild);
this.child.ordereredItems.forEach((item) => item._addParent(this));
}
}
};
TouchBar.TouchBarLabel = class TouchBarLabel extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'label')
this._addLiveProperty('label', config.label)
this._addLiveProperty('accessibilityLabel', config.accessibilityLabel)
this._addLiveProperty('textColor', config.textColor)
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'label');
this._addLiveProperty('label', config.label);
this._addLiveProperty('accessibilityLabel', config.accessibilityLabel);
this._addLiveProperty('textColor', config.textColor);
}
}
};
TouchBar.TouchBarPopover = class TouchBarPopover extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'popover')
this._addLiveProperty('label', config.label)
this._addLiveProperty('icon', config.icon)
this._addLiveProperty('showCloseButton', config.showCloseButton)
const defaultChild = (config.items instanceof TouchBar) ? config.items : new TouchBar(config.items)
this._addLiveProperty('child', defaultChild)
this.child.ordereredItems.forEach((item) => item._addParent(this))
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'popover');
this._addLiveProperty('label', config.label);
this._addLiveProperty('icon', config.icon);
this._addLiveProperty('showCloseButton', config.showCloseButton);
const defaultChild = (config.items instanceof TouchBar) ? config.items : new TouchBar(config.items);
this._addLiveProperty('child', defaultChild);
this.child.ordereredItems.forEach((item) => item._addParent(this));
}
}
};
TouchBar.TouchBarSlider = class TouchBarSlider extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'slider')
this._addLiveProperty('label', config.label)
this._addLiveProperty('minValue', config.minValue)
this._addLiveProperty('maxValue', config.maxValue)
this._addLiveProperty('value', config.value)
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'slider');
this._addLiveProperty('label', config.label);
this._addLiveProperty('minValue', config.minValue);
this._addLiveProperty('maxValue', config.maxValue);
this._addLiveProperty('value', config.value);
if (typeof config.change === 'function') {
this._addImmutableProperty('onInteraction', (details) => {
this._value = details.value
config.change(details.value)
})
this._value = details.value;
config.change(details.value);
});
}
}
}
};
TouchBar.TouchBarSpacer = class TouchBarSpacer extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'spacer')
this._addImmutableProperty('size', config.size)
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'spacer');
this._addImmutableProperty('size', config.size);
}
}
};
TouchBar.TouchBarSegmentedControl = class TouchBarSegmentedControl extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
this._addImmutableProperty('type', 'segmented_control')
this._addLiveProperty('segmentStyle', config.segmentStyle)
this._addLiveProperty('segments', config.segments || [])
this._addLiveProperty('selectedIndex', config.selectedIndex)
this._addLiveProperty('mode', config.mode)
super();
if (config == null) config = {};
this._addImmutableProperty('type', 'segmented_control');
this._addLiveProperty('segmentStyle', config.segmentStyle);
this._addLiveProperty('segments', config.segments || []);
this._addLiveProperty('selectedIndex', config.selectedIndex);
this._addLiveProperty('mode', config.mode);
if (typeof config.change === 'function') {
this._addImmutableProperty('onInteraction', (details) => {
this._selectedIndex = details.selectedIndex
config.change(details.selectedIndex, details.isSelected)
})
this._selectedIndex = details.selectedIndex;
config.change(details.selectedIndex, details.isSelected);
});
}
}
}
};
TouchBar.TouchBarScrubber = class TouchBarScrubber extends TouchBarItem {
constructor (config) {
super()
if (config == null) config = {}
let { select, highlight } = config
this._addImmutableProperty('type', 'scrubber')
this._addLiveProperty('items', config.items)
this._addLiveProperty('selectedStyle', config.selectedStyle || null)
this._addLiveProperty('overlayStyle', config.overlayStyle || null)
this._addLiveProperty('showArrowButtons', config.showArrowButtons || false)
this._addLiveProperty('mode', config.mode || 'free')
super();
if (config == null) config = {};
let { select, highlight } = config;
this._addImmutableProperty('type', 'scrubber');
this._addLiveProperty('items', config.items);
this._addLiveProperty('selectedStyle', config.selectedStyle || null);
this._addLiveProperty('overlayStyle', config.overlayStyle || null);
this._addLiveProperty('showArrowButtons', config.showArrowButtons || false);
this._addLiveProperty('mode', config.mode || 'free');
const cont = typeof config.continuous === 'undefined' ? true : config.continuous
this._addLiveProperty('continuous', cont)
const cont = typeof config.continuous === 'undefined' ? true : config.continuous;
this._addLiveProperty('continuous', cont);
if (typeof select === 'function' || typeof highlight === 'function') {
if (select == null) select = () => {}
if (highlight == null) highlight = () => {}
if (select == null) select = () => {};
if (highlight == null) highlight = () => {};
this._addImmutableProperty('onInteraction', (details) => {
if (details.type === 'select' && typeof select === 'function') {
select(details.selectedIndex)
select(details.selectedIndex);
} else if (details.type === 'highlight' && typeof highlight === 'function') {
highlight(details.highlightedIndex)
highlight(details.highlightedIndex);
}
})
});
}
}
}
};
module.exports = TouchBar
module.exports = TouchBar;

View File

@@ -1,9 +1,9 @@
'use strict'
'use strict';
const { EventEmitter } = require('events')
const { deprecate } = require('electron')
const { Tray } = process.electronBinding('tray')
const { EventEmitter } = require('events');
const { deprecate } = require('electron');
const { Tray } = process.electronBinding('tray');
Object.setPrototypeOf(Tray.prototype, EventEmitter.prototype)
Object.setPrototypeOf(Tray.prototype, EventEmitter.prototype);
module.exports = Tray
module.exports = Tray;

View File

@@ -1,11 +1,11 @@
'use strict'
'use strict';
const { EventEmitter } = require('events')
const { View } = process.electronBinding('view')
const { EventEmitter } = require('events');
const { View } = process.electronBinding('view');
Object.setPrototypeOf(View.prototype, EventEmitter.prototype)
Object.setPrototypeOf(View.prototype, EventEmitter.prototype);
View.prototype._init = function () {
}
};
module.exports = View
module.exports = View;

View File

@@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { LayoutManager } = electron
const { BoxLayout } = process.electronBinding('box_layout')
const { LayoutManager } = electron;
const { BoxLayout } = process.electronBinding('box_layout');
Object.setPrototypeOf(BoxLayout.prototype, LayoutManager.prototype)
Object.setPrototypeOf(BoxLayout.prototype, LayoutManager.prototype);
BoxLayout.prototype._init = function () {
// Call parent class's _init.
LayoutManager.prototype._init.call(this)
}
LayoutManager.prototype._init.call(this);
};
module.exports = BoxLayout
module.exports = BoxLayout;

View File

@@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { View } = electron
const { Button } = process.electronBinding('button')
const { View } = electron;
const { Button } = process.electronBinding('button');
Object.setPrototypeOf(Button.prototype, View.prototype)
Object.setPrototypeOf(Button.prototype, View.prototype);
Button.prototype._init = function () {
// Call parent class's _init.
View.prototype._init.call(this)
}
View.prototype._init.call(this);
};
module.exports = Button
module.exports = Button;

View File

@@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { Button } = electron
const { LabelButton } = process.electronBinding('label_button')
const { Button } = electron;
const { LabelButton } = process.electronBinding('label_button');
Object.setPrototypeOf(LabelButton.prototype, Button.prototype)
Object.setPrototypeOf(LabelButton.prototype, Button.prototype);
LabelButton.prototype._init = function () {
// Call parent class's _init.
Button.prototype._init.call(this)
}
Button.prototype._init.call(this);
};
module.exports = LabelButton
module.exports = LabelButton;

View File

@@ -1,8 +1,8 @@
'use strict'
'use strict';
const { LayoutManager } = process.electronBinding('layout_manager')
const { LayoutManager } = process.electronBinding('layout_manager');
LayoutManager.prototype._init = function () {
}
};
module.exports = LayoutManager
module.exports = LayoutManager;

View File

@@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { LabelButton } = electron
const { MdTextButton } = process.electronBinding('md_text_button')
const { LabelButton } = electron;
const { MdTextButton } = process.electronBinding('md_text_button');
Object.setPrototypeOf(MdTextButton.prototype, LabelButton.prototype)
Object.setPrototypeOf(MdTextButton.prototype, LabelButton.prototype);
MdTextButton.prototype._init = function () {
// Call parent class's _init.
LabelButton.prototype._init.call(this)
}
LabelButton.prototype._init.call(this);
};
module.exports = MdTextButton
module.exports = MdTextButton;

View File

@@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { View } = electron
const { ResizeArea } = process.electronBinding('resize_area')
const { View } = electron;
const { ResizeArea } = process.electronBinding('resize_area');
Object.setPrototypeOf(ResizeArea.prototype, View.prototype)
Object.setPrototypeOf(ResizeArea.prototype, View.prototype);
ResizeArea.prototype._init = function () {
// Call parent class's _init.
View.prototype._init.call(this)
}
View.prototype._init.call(this);
};
module.exports = ResizeArea
module.exports = ResizeArea;

View File

@@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { View } = electron
const { TextField } = process.electronBinding('text_field')
const { View } = electron;
const { TextField } = process.electronBinding('text_field');
Object.setPrototypeOf(TextField.prototype, View.prototype)
Object.setPrototypeOf(TextField.prototype, View.prototype);
TextField.prototype._init = function () {
// Call parent class's _init.
View.prototype._init.call(this)
}
View.prototype._init.call(this);
};
module.exports = TextField
module.exports = TextField;

View File

@@ -1,15 +1,15 @@
'use strict'
'use strict';
const electron = require('electron')
const electron = require('electron');
const { View } = electron
const { WebContentsView } = process.electronBinding('web_contents_view')
const { View } = electron;
const { WebContentsView } = process.electronBinding('web_contents_view');
Object.setPrototypeOf(WebContentsView.prototype, View.prototype)
Object.setPrototypeOf(WebContentsView.prototype, View.prototype);
WebContentsView.prototype._init = function () {
// Call parent class's _init.
View.prototype._init.call(this)
}
View.prototype._init.call(this);
};
module.exports = WebContentsView
module.exports = WebContentsView;

View File

@@ -1,26 +1,26 @@
'use strict'
'use strict';
const features = process.electronBinding('features')
const { EventEmitter } = require('events')
const electron = require('electron')
const path = require('path')
const url = require('url')
const { app, ipcMain, session, deprecate } = electron
const features = process.electronBinding('features');
const { EventEmitter } = require('events');
const electron = require('electron');
const path = require('path');
const url = require('url');
const { app, ipcMain, session, deprecate } = 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 { 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');
// session is not used here, the purpose is to make sure session is initalized
// before the webContents module.
// eslint-disable-next-line
session
let nextId = 0
let nextId = 0;
const getNextId = function () {
return ++nextId
}
return ++nextId;
};
// Stock page sizes
const PDFPageSizes = {
@@ -61,7 +61,7 @@ const PDFPageSizes = {
width_microns: 279400,
custom_display_name: 'Tabloid'
}
}
};
// Default printing setting
const defaultPrintingSetting = {
@@ -93,83 +93,83 @@ const defaultPrintingSetting = {
// 2 = color - see ColorModel in //printing/print_job_constants.h
color: 2,
collate: true
}
};
// JavaScript implementations of WebContents.
const binding = process.electronBinding('web_contents')
const { WebContents } = binding
const binding = process.electronBinding('web_contents');
const { WebContents } = binding;
Object.setPrototypeOf(NavigationController.prototype, EventEmitter.prototype)
Object.setPrototypeOf(WebContents.prototype, NavigationController.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')
throw new Error('Missing required channel argument');
}
const internal = false
const sendToAll = false
const internal = false;
const sendToAll = false;
return this._send(internal, sendToAll, channel, args)
}
return this._send(internal, sendToAll, channel, args);
};
WebContents.prototype.sendToAll = function (channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument')
throw new Error('Missing required channel argument');
}
const internal = false
const sendToAll = true
const internal = false;
const sendToAll = true;
return this._send(internal, sendToAll, channel, args)
}
return this._send(internal, sendToAll, channel, args);
};
WebContents.prototype._sendInternal = function (channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument')
throw new Error('Missing required channel argument');
}
const internal = true
const sendToAll = false
const internal = true;
const sendToAll = false;
return this._send(internal, sendToAll, channel, args)
}
return this._send(internal, sendToAll, channel, args);
};
WebContents.prototype._sendInternalToAll = function (channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument')
throw new Error('Missing required channel argument');
}
const internal = true
const sendToAll = true
const internal = true;
const sendToAll = true;
return this._send(internal, sendToAll, channel, args)
}
return this._send(internal, sendToAll, channel, args);
};
WebContents.prototype.sendToFrame = function (frameId, channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument')
throw new Error('Missing required channel argument');
} else if (typeof frameId !== 'number') {
throw new Error('Missing required frameId argument')
throw new Error('Missing required frameId argument');
}
const internal = false
const sendToAll = false
const internal = false;
const sendToAll = false;
return this._sendToFrame(internal, sendToAll, frameId, channel, args)
}
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
};
WebContents.prototype._sendToFrameInternal = function (frameId, channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument')
throw new Error('Missing required channel argument');
} else if (typeof frameId !== 'number') {
throw new Error('Missing required frameId argument')
throw new Error('Missing required frameId argument');
}
const internal = true
const sendToAll = false
const internal = true;
const sendToAll = false;
return this._sendToFrame(internal, sendToAll, frameId, channel, args)
}
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
};
// Following methods are mapped to webFrame.
const webFrameMethods = [
@@ -177,138 +177,138 @@ const webFrameMethods = [
'insertText',
'removeInsertedCSS',
'setVisualZoomLevelLimits'
]
];
for (const method of webFrameMethods) {
WebContents.prototype[method] = function (...args) {
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, ...args)
}
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, ...args);
};
}
const waitTillCanExecuteJavaScript = async (webContents) => {
if (webContents.getURL() && !webContents.isLoadingMainFrame()) return
if (webContents.getURL() && !webContents.isLoadingMainFrame()) return;
return new Promise((resolve) => {
webContents.once('did-stop-loading', () => {
resolve()
})
})
}
resolve();
});
});
};
// Make sure WebContents::executeJavaScript would run the code only when the
// 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', code, hasUserGesture)
}
await waitTillCanExecuteJavaScript(this);
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScript', code, hasUserGesture);
};
WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (code, hasUserGesture) {
await waitTillCanExecuteJavaScript(this)
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScriptInIsolatedWorld', code, hasUserGesture)
}
await waitTillCanExecuteJavaScript(this);
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScriptInIsolatedWorld', code, hasUserGesture);
};
// Translate the options of printToPDF.
WebContents.prototype.printToPDF = function (options) {
const printSettings = {
...defaultPrintingSetting,
requestID: getNextId()
}
};
if (options.landscape !== undefined) {
if (typeof options.landscape !== 'boolean') {
const error = new Error('landscape must be a Boolean')
return Promise.reject(error)
const error = new Error('landscape must be a Boolean');
return Promise.reject(error);
}
printSettings.landscape = options.landscape
printSettings.landscape = options.landscape;
}
if (options.scaleFactor !== undefined) {
if (typeof options.scaleFactor !== 'number') {
const error = new Error('scaleFactor must be a Number')
return Promise.reject(error)
const error = new Error('scaleFactor must be a Number');
return Promise.reject(error);
}
printSettings.scaleFactor = options.scaleFactor
printSettings.scaleFactor = options.scaleFactor;
}
if (options.marginsType !== undefined) {
if (typeof options.marginsType !== 'number') {
const error = new Error('marginsType must be a Number')
return Promise.reject(error)
const error = new Error('marginsType must be a Number');
return Promise.reject(error);
}
printSettings.marginsType = options.marginsType
printSettings.marginsType = options.marginsType;
}
if (options.printSelectionOnly !== undefined) {
if (typeof options.printSelectionOnly !== 'boolean') {
const error = new Error('printSelectionOnly must be a Boolean')
return Promise.reject(error)
const error = new Error('printSelectionOnly must be a Boolean');
return Promise.reject(error);
}
printSettings.shouldPrintSelectionOnly = options.printSelectionOnly
printSettings.shouldPrintSelectionOnly = options.printSelectionOnly;
}
if (options.printBackground !== undefined) {
if (typeof options.printBackground !== 'boolean') {
const error = new Error('printBackground must be a Boolean')
return Promise.reject(error)
const error = new Error('printBackground must be a Boolean');
return Promise.reject(error);
}
printSettings.shouldPrintBackgrounds = options.printBackground
printSettings.shouldPrintBackgrounds = options.printBackground;
}
if (options.pageRanges !== undefined) {
const pageRanges = options.pageRanges
const pageRanges = options.pageRanges;
if (!pageRanges.hasOwnProperty('from') || !pageRanges.hasOwnProperty('to')) {
const error = new Error(`pageRanges must be an Object with 'from' and 'to' properties`)
return Promise.reject(error)
const error = new Error(`pageRanges must be an Object with 'from' and 'to' properties`);
return Promise.reject(error);
}
if (typeof pageRanges.from !== 'number') {
const error = new Error('pageRanges.from must be a Number')
return Promise.reject(error)
const error = new Error('pageRanges.from must be a Number');
return Promise.reject(error);
}
if (typeof pageRanges.to !== 'number') {
const error = new Error('pageRanges.to must be a Number')
return Promise.reject(error)
const error = new Error('pageRanges.to must be a Number');
return Promise.reject(error);
}
// Chromium uses 1-based page ranges, so increment each by 1.
printSettings.pageRange = [{
from: pageRanges.from + 1,
to: pageRanges.to + 1
}]
}];
}
if (options.headerFooter !== undefined) {
const headerFooter = options.headerFooter
printSettings.headerFooterEnabled = true
const headerFooter = options.headerFooter;
printSettings.headerFooterEnabled = true;
if (typeof headerFooter === 'object') {
if (!headerFooter.url || !headerFooter.title) {
const error = new Error('url and title properties are required for headerFooter')
return Promise.reject(error)
const error = new Error('url and title properties are required for headerFooter');
return Promise.reject(error);
}
if (typeof headerFooter.title !== 'string') {
const error = new Error('headerFooter.title must be a String')
return Promise.reject(error)
const error = new Error('headerFooter.title must be a String');
return Promise.reject(error);
}
printSettings.title = headerFooter.title
printSettings.title = headerFooter.title;
if (typeof headerFooter.url !== 'string') {
const error = new Error('headerFooter.url must be a String')
return Promise.reject(error)
const error = new Error('headerFooter.url must be a String');
return Promise.reject(error);
}
printSettings.url = headerFooter.url
printSettings.url = headerFooter.url;
} else {
const error = new Error('headerFooter must be an Object')
return Promise.reject(error)
const error = new Error('headerFooter must be an Object');
return Promise.reject(error);
}
}
// Optionally set size for PDF.
if (options.pageSize !== undefined) {
const pageSize = options.pageSize
const pageSize = options.pageSize;
if (typeof pageSize === 'object') {
if (!pageSize.height || !pageSize.width) {
const error = new Error('height and width properties are required for pageSize')
return Promise.reject(error)
const error = new Error('height and width properties are required for pageSize');
return Promise.reject(error);
}
// Dimensions in Microns
// 1 meter = 10^6 microns
@@ -317,28 +317,28 @@ WebContents.prototype.printToPDF = function (options) {
custom_display_name: 'Custom',
height_microns: Math.ceil(pageSize.height),
width_microns: Math.ceil(pageSize.width)
}
};
} else if (PDFPageSizes[pageSize]) {
printSettings.mediaSize = PDFPageSizes[pageSize]
printSettings.mediaSize = PDFPageSizes[pageSize];
} else {
const error = new Error(`Unsupported pageSize: ${pageSize}`)
return Promise.reject(error)
const error = new Error(`Unsupported pageSize: ${pageSize}`);
return Promise.reject(error);
}
} else {
printSettings.mediaSize = PDFPageSizes['A4']
printSettings.mediaSize = PDFPageSizes['A4'];
}
// Chromium expects this in a 0-100 range number, not as float
printSettings.scaleFactor = Math.ceil(printSettings.scaleFactor) % 100
printSettings.scaleFactor = Math.ceil(printSettings.scaleFactor) % 100;
// PrinterType enum from //printing/print_job_constants.h
printSettings.printerType = 2
printSettings.printerType = 2;
if (features.isPrintingEnabled()) {
return this._printToPDF(printSettings)
return this._printToPDF(printSettings);
} else {
const error = new Error('Printing feature is disabled')
return Promise.reject(error)
const error = new Error('Printing feature is disabled');
return Promise.reject(error);
}
}
};
WebContents.prototype.print = function (options = {}, callback) {
// TODO(codebytere): deduplicate argument sanitization by moving rest of
@@ -346,10 +346,10 @@ WebContents.prototype.print = function (options = {}, callback) {
if (typeof options === 'object') {
// Optionally set size for PDF.
if (options.pageSize !== undefined) {
const pageSize = options.pageSize
const pageSize = options.pageSize;
if (typeof pageSize === 'object') {
if (!pageSize.height || !pageSize.width) {
throw new Error('height and width properties are required for pageSize')
throw new Error('height and width properties are required for pageSize');
}
// Dimensions in Microns - 1 meter = 10^6 microns
options.mediaSize = {
@@ -357,40 +357,40 @@ WebContents.prototype.print = function (options = {}, callback) {
custom_display_name: 'Custom',
height_microns: Math.ceil(pageSize.height),
width_microns: Math.ceil(pageSize.width)
}
};
} else if (PDFPageSizes[pageSize]) {
options.mediaSize = PDFPageSizes[pageSize]
options.mediaSize = PDFPageSizes[pageSize];
} else {
throw new Error(`Unsupported pageSize: ${pageSize}`)
throw new Error(`Unsupported pageSize: ${pageSize}`);
}
}
}
if (features.isPrintingEnabled()) {
if (callback) {
this._print(options, callback)
this._print(options, callback);
} else {
this._print(options)
this._print(options);
}
} else {
console.error('Error: Printing feature is disabled.')
console.error('Error: Printing feature is disabled.');
}
}
};
WebContents.prototype.getPrinters = function () {
if (features.isPrintingEnabled()) {
return this._getPrinters()
return this._getPrinters();
} else {
console.error('Error: Printing feature is disabled.')
return []
console.error('Error: Printing feature is disabled.');
return [];
}
}
};
WebContents.prototype.loadFile = function (filePath, options = {}) {
if (typeof filePath !== 'string') {
throw new Error('Must pass filePath as a string')
throw new Error('Must pass filePath as a string');
}
const { query, search, hash } = options
const { query, search, hash } = options;
return this.loadURL(url.format({
protocol: 'file',
@@ -399,99 +399,99 @@ WebContents.prototype.loadFile = function (filePath, options = {}) {
query,
search,
hash
}))
}
}));
};
const addReplyToEvent = (event) => {
event.reply = (...args) => {
event.sender.sendToFrame(event.frameId, ...args)
}
}
event.sender.sendToFrame(event.frameId, ...args);
};
};
const addReplyInternalToEvent = (event) => {
Object.defineProperty(event, '_replyInternal', {
configurable: false,
enumerable: false,
value: (...args) => {
event.sender._sendToFrameInternal(event.frameId, ...args)
event.sender._sendToFrameInternal(event.frameId, ...args);
}
})
}
});
};
const addReturnValueToEvent = (event) => {
Object.defineProperty(event, 'returnValue', {
set: (value) => event.sendReply([value]),
get: () => {}
})
}
});
};
// Add JavaScript wrappers for WebContents class.
WebContents.prototype._init = function () {
// The navigation controller.
NavigationController.call(this, this)
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)
this.setMaxListeners(0);
// Dispatch IPC messages to the ipc module.
this.on('-ipc-message', function (event, internal, channel, args) {
if (internal) {
addReplyInternalToEvent(event)
ipcMainInternal.emit(channel, event, ...args)
addReplyInternalToEvent(event);
ipcMainInternal.emit(channel, event, ...args);
} else {
addReplyToEvent(event)
this.emit('ipc-message', event, channel, ...args)
ipcMain.emit(channel, event, ...args)
addReplyToEvent(event);
this.emit('ipc-message', event, channel, ...args);
ipcMain.emit(channel, event, ...args);
}
})
});
this.on('-ipc-invoke', function (event, internal, channel, args) {
event._reply = (result) => event.sendReply({ result })
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
console.error(`Error occurred in handler for '${channel}':`, error);
event.sendReply({ error: error.toString() });
};
const target = internal ? ipcMainInternal : ipcMain;
if (target._invokeHandlers.has(channel)) {
target._invokeHandlers.get(channel)(event, ...args)
target._invokeHandlers.get(channel)(event, ...args);
} else {
event._throw(`No handler registered for '${channel}'`)
event._throw(`No handler registered for '${channel}'`);
}
})
});
this.on('-ipc-message-sync', function (event, internal, channel, args) {
addReturnValueToEvent(event)
addReturnValueToEvent(event);
if (internal) {
addReplyInternalToEvent(event)
ipcMainInternal.emit(channel, event, ...args)
addReplyInternalToEvent(event);
ipcMainInternal.emit(channel, event, ...args);
} else {
addReplyToEvent(event)
this.emit('ipc-message-sync', event, channel, ...args)
ipcMain.emit(channel, event, ...args)
addReplyToEvent(event);
this.emit('ipc-message-sync', event, channel, ...args);
ipcMain.emit(channel, event, ...args);
}
})
});
// Handle context menu action request from pepper plugin.
this.on('pepper-context-menu', function (event, params, callback) {
// Access Menu via electron.Menu to prevent circular require.
const menu = electron.Menu.buildFromTemplate(params.menu)
const menu = electron.Menu.buildFromTemplate(params.menu);
menu.popup({
window: event.sender.getOwnerBrowserWindow(),
x: params.x,
y: params.y,
callback
})
})
});
});
this.on('crashed', (event, ...args) => {
app.emit('renderer-process-crashed', event, this, ...args)
})
app.emit('renderer-process-crashed', event, this, ...args);
});
// The devtools requests the webContents to reload.
this.on('devtools-reload-page', function () {
this.reload()
})
this.reload();
});
// Handle window.open for BrowserWindow and BrowserView.
if (['browserView', 'window'].includes(this.getType())) {
@@ -503,9 +503,9 @@ WebContents.prototype._init = function () {
show: true,
width: 800,
height: 600
}
internalWindowOpen(event, url, referrer, frameName, disposition, options, additionalFeatures, postData)
})
};
internalWindowOpen(event, url, referrer, frameName, disposition, options, additionalFeatures, postData);
});
// Create a new browser window for the native implementation of
// "window.open", used in sandbox and nativeWindowOpen mode.
@@ -513,8 +513,8 @@ WebContents.prototype._init = function () {
userGesture, left, top, width, height, url, frameName) => {
if ((disposition !== 'foreground-tab' && disposition !== 'new-window' &&
disposition !== 'background-tab')) {
event.preventDefault()
return
event.preventDefault();
return;
}
const options = {
@@ -524,54 +524,74 @@ WebContents.prototype._init = function () {
width: width || 800,
height: height || 600,
webContents
}
const referrer = { url: '', policy: 'default' }
internalWindowOpen(event, url, referrer, frameName, disposition, options)
})
};
const referrer = { url: '', policy: 'default' };
internalWindowOpen(event, url, referrer, frameName, disposition, options);
});
}
this.on('login', (event, ...args) => {
app.emit('login', event, this, ...args)
})
app.emit('login', event, this, ...args);
});
const event = process.electronBinding('event').createEmpty()
app.emit('web-contents-created', event, this)
}
const event = process.electronBinding('event').createEmpty();
app.emit('web-contents-created', event, this);
// Deprecations
deprecate.fnToProperty(WebContents.prototype, 'audioMuted', '_isAudioMuted', '_setAudioMuted')
deprecate.fnToProperty(WebContents.prototype, 'userAgent', '_getUserAgent', '_setUserAgent')
deprecate.fnToProperty(WebContents.prototype, 'zoomLevel', '_getZoomLevel', '_setZoomLevel')
deprecate.fnToProperty(WebContents.prototype, 'zoomFactor', '_getZoomFactor', '_setZoomFactor')
deprecate.fnToProperty(WebContents.prototype, 'frameRate', '_getFrameRate', '_setFrameRate')
// Properties
Object.defineProperty(this, 'audioMuted', {
get: () => this.isAudioMuted(),
set: (muted) => this.setAudioMuted(muted)
});
Object.defineProperty(this, 'userAgent', {
get: () => this.getUserAgent(),
set: (agent) => this.setUserAgent(agent)
});
Object.defineProperty(this, 'zoomLevel', {
get: () => this.getZoomLevel(),
set: (level) => this.setZoomLevel(level)
});
Object.defineProperty(this, 'zoomFactor', {
get: () => this.getZoomFactor(),
set: (factor) => this.setZoomFactor(factor)
});
Object.defineProperty(this, 'frameRate', {
get: () => this.getFrameRate(),
set: (rate) => this.setFrameRate(rate)
});
};
// JavaScript wrapper of Debugger.
const { Debugger } = process.electronBinding('debugger')
Object.setPrototypeOf(Debugger.prototype, EventEmitter.prototype)
const { Debugger } = process.electronBinding('debugger');
Object.setPrototypeOf(Debugger.prototype, EventEmitter.prototype);
// Public APIs.
module.exports = {
create (options = {}) {
return binding.create(options)
return binding.create(options);
},
fromId (id) {
return binding.fromId(id)
return binding.fromId(id);
},
getFocusedWebContents () {
let focused = null
let focused = null;
for (const contents of binding.getAllWebContents()) {
if (!contents.isFocused()) continue
if (focused == null) focused = contents
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
if (contents.getType() === 'webview') return contents;
}
return focused
return focused;
},
getAllWebContents () {
return binding.getAllWebContents()
return binding.getAllWebContents();
}
}
};

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