Compare commits

...

77 Commits

Author SHA1 Message Date
Electron Bot
1abd36f6c8 Bump v13.0.0-nightly.20201208 2020-12-08 06:33:18 -08:00
David Sanders
788e51127f chore: blank lines before lists in markdown (#26793) 2020-12-08 16:08:19 +09:00
Milan Burda
ee0550efca fix: systemPreferences.effectiveAppearance returning systemPreferences.getAppLevelAppearance() (#26852) 2020-12-08 16:07:04 +09:00
Shelley Vohr
b788ceb7bd fix: screen EventEmitter methods with remote (#26809)
* fix: screen EventEmitter methods with remote

* Review feedback
2020-12-08 13:47:48 +09:00
Erick Zhao
e87061398b docs: update OSR max FPS number (#26805) 2020-12-08 13:41:09 +09:00
Milan Burda
c9b813a1f9 refactor: convert more C++ enums to C++11 enum classes (#26850) 2020-12-08 13:39:33 +09:00
Mark Lee
3bc220db29 docs: clean up the native modules documentation (#26813) 2020-12-08 13:28:59 +09:00
windwalkr
6001f03e46 docs: add description to read-me.md (#26823)
Unhandled exception error is received if description is not defined while running "npm run make."  Defining a description solves this issue.
2020-12-08 13:26:29 +09:00
Samuel Attard
771e34a53a feat: route frame based permission checks through our permission check handler (#19903)
* feat: route frame based permission checks through our permission check handler

* docs: add change to setPermissionCheckHandler to breaking changes doc
2020-12-07 15:44:56 -08:00
Samuel Attard
3db4e612f4 fix: handle security warnings promise when JS is disabled (#26837) 2020-12-07 10:58:00 -08:00
Mimi
03b43e4d8c build: use python3 for electron hooks (#26839) 2020-12-07 10:57:41 -08:00
Alexey Kuzmin
e89b3ca1d1 fix: add a "set" trap to the "screen" module proxy (#26818) 2020-12-07 09:20:50 -08:00
Jeremy Rose
d3b1566181 chore: remove unused _replyInternal method (#26825) 2020-12-07 09:19:26 -08:00
Electron Bot
5a5d964720 Bump v13.0.0-nightly.20201207 2020-12-07 06:31:40 -08:00
Shelley Vohr
228a184b48 chore: remove unused FindByID helper (#26826) 2020-12-06 09:33:02 -08:00
Nikita Kot
7672aa9525 feat: exposeInMainWorld allow to expose non-object APIs (#26594) 2020-12-04 09:43:20 -08:00
Milan Burda
b111bba387 fix: send IPC_MESSAGES.RENDERER_RELEASE_CALLBACK as internal message (#26808) 2020-12-04 19:09:08 +03:00
Electron Bot
b133b6fd45 Bump v13.0.0-nightly.20201204 2020-12-04 06:32:29 -08:00
Electron Bot
45eee46864 Bump v13.0.0-nightly.20201203 2020-12-03 06:32:05 -08:00
Eli Skeggs
5521f8acca feat: allow path override with --ignore-scripts (#25377)
If you --ignore-scripts when installing electron currently, it'll fail
to write the path.txt file and thus fail to use the override dist path.
Open to other solutions - just hoping to be able to use a prebuilt
electron binary with the default package without having to muck around
with it installing an unused version.
2020-12-03 16:23:44 +09:00
Milan Burda
b37982987a chore: remove unused sendToAll + related APIs (#26771)
* chore: remove unused sendToAll + related APIs

* refactor: no need to args.ShallowClone() anymore
2020-12-03 15:55:50 +09:00
Electron Bot
8eee9d1290 Bump v13.0.0-nightly.20201202 2020-12-02 06:32:14 -08:00
Antonio
6fc5ff77c1 docs: app distribution page (#26239)
* docs: first draft of the app distribution page

* docs: second iteration of the app distribution page. Fixed mentions

* docs: third iteration of the app distribution page. Fixed mentions

* docs: reworked app distribution page according to mentions

* docs: minor fixes to the app distribution page according to mentions
2020-12-02 15:52:12 +09:00
Cheng Zhao
cffb51e141 chore: remove TODO on SetHidden calls (#26746) 2020-12-01 21:36:23 -08:00
Shelley Vohr
e96fa95b94 fix: properly emit after hooks after exception (#26752) 2020-12-01 21:34:08 -08:00
Vadim
efca7007b6 fix: internalModuleReadJSON for unpacked JSON (#26749) 2020-12-01 21:33:39 -08:00
Milan Burda
c2909a3b8d docs: BrowserWindow extension APIs are deprecated in Electron 9 (#26722) 2020-12-01 18:27:19 -06:00
Jim Fisher
430189fa84 docs: fix contentTracing code sample (#26737) 2020-12-01 15:45:45 -08:00
Shelley Vohr
94381cda49 docs: add debugging vars to env var doc (#26743) 2020-12-01 15:04:07 -08:00
Shelley Vohr
528b0f0e74 fix: draggable views on BrowserViews on Windows (#26738) 2020-12-01 15:03:00 -08:00
PalmerAL
cdcee04bbe fix: Add default Bluetooth permission strings (#26730) 2020-12-01 11:34:39 -08:00
Electron Bot
6c5f7a6e86 Bump v13.0.0-nightly.20201201 2020-12-01 06:33:16 -08:00
Michaela Laurencin
32d4c9ad85 fix: add check in IsMaximized for non-WS_THICKFRAME windows (#26586)
* fix: add check in IsMaximized for non-WS_THICKFRAME windows

* remove logs

* change GetPosition for GetNativeWindow

* change GetPosition for GetNativeWindow in IsMaximize

* add top left corner check

* add transparent maximization test

* replace window and display comparison

* rebase off master
2020-12-01 15:27:58 +09:00
Shelley Vohr
acfbbe9869 fix: draggable regions calculation in BrowserWindow/BrowserView (#26690) 2020-11-30 21:02:04 -08:00
Milan Burda
4e3e3d414d refactor: simplify child process tracking for app.getAppMetrics() (#26657) 2020-12-01 10:47:46 +09:00
David Sanders
61f339d3aa chore: use ESLint API for linting (#26705)
* chore: use ESLint API for linting

* chore: fix typo

* chore: fix import
2020-12-01 10:47:29 +09:00
Antonio
cf970f31a3 docs: revised offscreen rendering page (#26542)
* docs: revised offscreen rendering page

* docs: reworked offscreen rendering page according to mentions

* docs: minor revision of offscreen rendering

* docs: fixed trailing space in offscreen rendering

* docs: resolved merge conflict
2020-12-01 10:47:09 +09:00
Jeremy Rose
9c26be7b43 test: deflake current-render-view-deleted test (#26698) 2020-11-30 17:06:25 -08:00
Milan Burda
19954126e0 chore: remove deprecated extension APIs (#26696) 2020-11-30 14:40:56 -08:00
Samuel Attard
7d49ce898a build: use all-for-one goma (#26699)
* Revert "Revert "build: use one-for-all goma (#26679)" (#26689)"

This reverts commit 38ab829ea6.

* build: ensure file descriptor limit is higher on macOS
2020-11-30 12:29:36 -08:00
Milan Burda
09d7b2bc91 chore: remove deprecated shell.moveItemToTrash() (#26723) 2020-11-30 23:25:03 +03:00
Electron Bot
59b4d5c156 Bump v13.0.0-nightly.20201130 2020-11-30 06:32:52 -08:00
Erick Zhao
36af8022ca fix: delay emitting NotifyIcon events on Windows (#26668)
* wip?

* attempt to use weakptr

* apply posttask change to other balloon events

* chore: add clarifying comment on weakptr

* refactor: move weakptr include to implementation

(it's not needed in the header file)

* refactor: use default initializer for weak factory

* refactor: move weakptr usage outside of loop

* fix: convert mouse events as well

* refactor: use member function for balloon events

* fix: check if wicon is truthy in callback

* refactor: bind mouse events with member function

* refactor: inline lparams

* refactor: inline getkeyboardmodifiers()

* chore: correct GetKeyboardModifiers typo
2020-11-30 16:49:30 +09:00
Milan Burda
14c8e000cb feat: add process.uptime() to sandboxed renderers (#26684) 2020-11-30 16:49:18 +09:00
David Sanders
c8c41fb727 chore: fixup patches linting (#26595) 2020-11-30 16:49:01 +09:00
Antonio
fadd513739 docs: added fiddle support for code samples (#26501)
* docs: added fiddle support for code samples in quick start guide and features

* docs: removed excessive fiddle links for not final steps

* docs: added eof newlines to fiddle examples

* docs: reworked fiddle examples to be more self-sufficient

* docs: reworked fiddle examples according to mentions

* docs: changed http to https in the offscreen rendering fiddle

* docs: fix recent documents fiddle to be more consistent
2020-11-30 16:48:39 +09:00
Jeremy Rose
770e245de5 fix: uaf in WebContents::DidStopLoading (#26702) 2020-11-29 21:03:07 -08:00
Samuel Attard
7cc571801c build: remove sccache (#26701) 2020-11-28 21:28:57 -08:00
Electron Bot
8311ea1a36 Bump v13.0.0-nightly.20201127 2020-11-27 06:31:41 -08:00
Milan Burda
022bafc485 chore: remove deprecated crashReporter APIs (#26695) 2020-11-26 22:07:40 +03:00
Electron Bot
d0cf16263e Bump v13.0.0-nightly.20201126 2020-11-26 06:32:13 -08:00
Jeremy Rose
ba629e3127 fix: use-after-free in ElectronBrowserContext during shutdown (#26680) 2020-11-25 12:29:26 -08:00
Electron Bot
662077f153 Bump v13.0.0-nightly.20201125 2020-11-25 06:31:41 -08:00
Cheng Zhao
d56861eaa5 chore: add descriptions for patches (#26671) 2020-11-25 21:50:46 +09:00
Robo
38ab829ea6 Revert "build: use one-for-all goma (#26679)" (#26689)
This reverts commit 6761814f14.
2020-11-24 22:00:48 -08:00
David Sanders
87e20f2b97 chore: tidy up docs markdown (#26666) 2020-11-24 18:52:46 -08:00
Samuel Attard
6761814f14 build: use one-for-all goma (#26679)
* build: use one-for-all goma

* build: use 300 everywhere
2020-11-24 15:11:22 -08:00
Milan Burda
c8d77cae4a refactor: replace V8 hidden values with WeakMap / WeakSet (#26659) 2020-11-24 16:11:39 -05:00
David Sanders
0be6c92aa9 chore: include alt text for images in markdown (#26665)
* chore: include alt text for images in markdown

* chore: fix typo
2020-11-24 10:50:10 -05:00
Electron Bot
956892dd5b Bump v13.0.0-nightly.20201124 2020-11-24 06:32:16 -08:00
Devin Foley
a5c612cd96 fix: Update Squirrel.mac to fix permissions bug. (#26358)
* fix: Update Squirrel.mac to fix permissions bug.

* Update patches.
2020-11-24 17:38:22 +09:00
Jeremy Rose
9d54fdfd12 fix: crash on exit in Event destructor (#26537) 2020-11-24 15:41:06 +09:00
Samuel Attard
b894151745 build: update npx.py to support npx@7 (#26662)
* build: update npx.py to support npx@7

* build: set npm_config_yes for all npx callsites
2020-11-23 21:26:54 -08:00
David Sanders
e455a79218 chore: use relative links in docs (#26360) 2020-11-24 11:02:16 +09:00
Anders Kaseorg
b1b25607ee fix: make screen wrapper remote-friendly again (#26620)
This restores accessibility of screen methods via remote.screen.

Fixes #26610.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2020-11-23 16:44:54 -05:00
Milan Burda
6932e02eb8 refactor: use getWebPreference() for all options (#26531) 2020-11-23 22:39:08 +03:00
Jeremy Rose
854d2b1574 fix: reject contentTracing.stopRecording on failure (#26608) 2020-11-23 10:20:40 -08:00
Jeremy Rose
329494cfeb fix: segfault on webContents.fromId(xxx) (#26609) 2020-11-23 09:21:00 -08:00
David Sanders
abb1504ecc docs: use asterisks for unordered lists (#26552) 2020-11-23 12:15:27 -05:00
Shelley Vohr
b57ae67da6 chore: update nmv for Electron v13 (#26581) 2020-11-23 11:14:25 -05:00
Electron Bot
2e239ea563 Bump v13.0.0-nightly.20201123 2020-11-23 06:31:59 -08:00
Electron Bot
7c099210b4 Bump v13.0.0-nightly.20201120 2020-11-20 06:31:20 -08:00
Shelley Vohr
46972abf8b refactor: align shutdown signal handling with upstream (#26559) 2020-11-19 16:00:34 -08:00
Milan Burda
b4196ca486 build: fix build with enable_printing=false (#26597) 2020-11-19 10:05:49 -05:00
Electron Bot
06158b3e94 Bump v13.0.0-nightly.20201119 2020-11-19 06:33:44 -08:00
David Sanders
18f004eab1 docs: fix relative link (#26585) 2020-11-19 16:06:32 +09:00
David Sanders
03a70896c7 chore: tidy up markdown (#26554) 2020-11-18 20:58:47 -08:00
186 changed files with 2196 additions and 1559 deletions

View File

@@ -295,10 +295,10 @@ step-setup-goma-for-build: &step-setup-goma-for-build
run:
name: Setup Goma
command: |
if [ "`uname`" == "Linux" ]; then
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
else
echo 'export NUMBER_OF_NINJA_PROCESSES=25' >> $BASH_ENV
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
if [ "`uname`" == "Darwin" ]; then
echo 'ulimit -n 10000' >> $BASH_ENV
echo 'sudo launchctl limit maxfiles 65536 200000' >> $BASH_ENV
fi
if [ ! -z "$RAW_GOMA_AUTH" ]; then
echo $RAW_GOMA_AUTH > ~/.goma_oauth2_config
@@ -307,7 +307,7 @@ step-setup-goma-for-build: &step-setup-goma-for-build
cd build-tools
npm install
mkdir third_party
node -e "require('./src/utils/goma.js').downloadAndPrepare()"
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
node -e "require('./src/utils/goma.js').ensure()"
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
echo 'export LOCAL_GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
@@ -445,9 +445,6 @@ step-fix-sync-on-mac: &step-fix-sync-on-mac
# Fix Clang Install (wrong binary)
rm -rf src/third_party/llvm-build
python src/tools/clang/scripts/update.py
# Fix Framework Header Installs (symlinks not retained)
rm -rf src/electron/external_binaries
python src/electron/script/update-external-binaries.py
fi
step-install-signing-cert-on-mac: &step-install-signing-cert-on-mac

View File

@@ -2,8 +2,8 @@
As a member project of the OpenJS Foundation, Electron uses [Contributor Covenant v2.0](https://contributor-covenant.org/version/2/0/code_of_conduct) as their code of conduct. The full text is included [below](#contributor-covenant-code-of-conduct) in English, and translations are available from the Contributor Covenant organisation:
- [contributor-covenant.org/translations](https://www.contributor-covenant.org/translations)
- [github.com/ContributorCovenant](https://github.com/ContributorCovenant/contributor_covenant/tree/release/content/version/2/0)
* [contributor-covenant.org/translations](https://www.contributor-covenant.org/translations)
* [github.com/ContributorCovenant](https://github.com/ContributorCovenant/contributor_covenant/tree/release/content/version/2/0)
## Contributor Covenant Code of Conduct

View File

@@ -29,7 +29,7 @@ _If an issue has been closed and you still feel it's relevant, feel free to ping
### Languages
We accept issues in *any* language.
When an issue is posted in a language besides English, it is acceptable and encouraged to post an English-translated copy as a reply.
When an issue is posted in a language besides English, it is acceptable and encouraged to post an English-translated copy as a reply.
Anyone may post the translated reply.
In most cases, a quick pass through translation software is sufficient.
Having the original text _as well as_ the translation can help mitigate translation errors.
@@ -66,5 +66,5 @@ See [Coding Style](https://electronjs.org/docs/development/coding-style) for inf
## Further Reading
For more in-depth guides on developing Electron, see
For more in-depth guides on developing Electron, see
[/docs/development](/docs/development/README.md)

19
DEPS
View File

@@ -20,7 +20,7 @@ vars = {
'nan_version':
'2c4ee8a32a299eada3cd6e468bbd0a473bfea96d',
'squirrel.mac_version':
'a3a5b3f03b824441c014893b18f99a103b2603e9',
'cdc0729c8bf8576bfef18629186e1e9ecf1b0d9f',
'pyyaml_version': '3.12',
'requests_version': 'e4d59bedfd3c7f4f254f4f5d036587bcd8152458',
@@ -58,10 +58,6 @@ vars = {
# To allow running hooks without parsing the DEPS tree
'process_deps': True,
# It is always needed for normal Electron builds,
# but might be impossible for custom in-house builds.
'download_external_binaries': True,
'checkout_nacl':
False,
'checkout_libaom':
@@ -157,22 +153,13 @@ hooks = [
'src/electron/patches/mtime-cache.json',
],
},
{
'name': 'electron_external_binaries',
'pattern': 'src/electron/script/update-external-binaries.py',
'condition': 'download_external_binaries',
'action': [
'python3',
'src/electron/script/update-external-binaries.py',
],
},
{
'name': 'electron_npm_deps',
'pattern': 'src/electron/package.json',
'action': [
'python3',
'-c',
'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python", "script/lib/npx.py", "yarn@' + (Var("yarn_version")) + '", "install", "--frozen-lockfile"]);',
'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python3", "script/lib/npx.py", "yarn@' + (Var("yarn_version")) + '", "install", "--frozen-lockfile"]);',
],
},
{
@@ -182,7 +169,7 @@ hooks = [
'action': [
'python3',
'-c',
'import os, subprocess; os.chdir(os.path.join("src", "electron", "vendor", "requests")); subprocess.check_call(["python", "setup.py", "build"]);',
'import os, subprocess; os.chdir(os.path.join("src", "electron", "vendor", "requests")); subprocess.check_call(["python3", "setup.py", "build"]);',
],
},
]

View File

@@ -1 +1 @@
12.0.0-nightly.20201118
13.0.0-nightly.20201208

View File

@@ -1,6 +1,5 @@
[![Electron Logo](https://electronjs.org/images/electron-logo.svg)](https://electronjs.org)
[![CircleCI Build Status](https://circleci.com/gh/electron/electron/tree/master.svg?style=shield)](https://circleci.com/gh/electron/electron/tree/master)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/4lggi9dpjc1qob7k/branch/master?svg=true)](https://ci.appveyor.com/project/electron-bot/electron-ljo26/branch/master)
[![devDependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron?type=dev)

View File

@@ -13,4 +13,5 @@ Report security bugs in third-party modules to the person or team maintaining th
For context on Electron's security notification process, please see the [Notifications](https://github.com/electron/governance/blob/master/wg-security/membership-and-notifications.md#notifications) section of the Security WG's [Membership and Notifications](https://github.com/electron/governance/blob/master/wg-security/membership-and-notifications.md) Governance document.
## Learning More About Security
To learn more about securing an Electron application, please see the [security tutorial](docs/tutorial/security.md).

View File

@@ -98,8 +98,6 @@ build_script:
$env:SAVE_GCLIENT_SRC="true"
}
} else {
# update external binaries
python src/electron/script/update-external-binaries.py
# update angle
cd src\third_party\angle
git remote set-url origin https://chromium.googlesource.com/angle/angle.git
@@ -141,7 +139,8 @@ build_script:
- cd build-tools
- npm install
- mkdir third_party
- node -e "require('./src/utils/goma.js').downloadAndPrepare()"
- ps: >-
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
- cd ..

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 = 87
node_module_version = 89
v8_promise_internal_field_count = 1
v8_typed_array_max_size_in_heap = 0

View File

@@ -91,11 +91,6 @@ These individual tutorials expand on topics discussed in the guide above.
* Electron Releases & Developer Feedback
* [Versioning Policy](tutorial/electron-versioning.md)
* [Release Timelines](tutorial/electron-timelines.md)
* [Packaging App Source Code with asar](tutorial/application-packaging.md)
* [Generating asar Archives](tutorial/application-packaging.md#generating-asar-archives)
* [Using asar Archives](tutorial/application-packaging.md#using-asar-archives)
* [Limitations](tutorial/application-packaging.md#limitations-of-the-node-api)
* [Adding Unpacked Files to asar Archives](tutorial/application-packaging.md#adding-unpacked-files-to-asar-archives)
* [Testing Widevine CDM](tutorial/testing-widevine-cdm.md)
---

View File

@@ -723,94 +723,6 @@ Returns `BrowserWindow | null` - The window that owns the given `browserView`. I
Returns `BrowserWindow | null` - The window with the given `id`.
#### `BrowserWindow.addExtension(path)` _Deprecated_
* `path` String
Adds Chrome extension located at `path`, and returns extension's name.
The method will also not return if the extension's manifest is missing or incomplete.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
**Note:** This method is deprecated. Instead, use
[`ses.loadExtension(path)`](session.md#sesloadextensionpath).
#### `BrowserWindow.removeExtension(name)` _Deprecated_
* `name` String
Remove a Chrome extension by name.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
**Note:** This method is deprecated. Instead, use
[`ses.removeExtension(extension_id)`](session.md#sesremoveextensionextensionid).
#### `BrowserWindow.getExtensions()` _Deprecated_
Returns `Record<String, ExtensionInfo>` - The keys are the extension names and each value is
an Object containing `name` and `version` properties.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
**Note:** This method is deprecated. Instead, use
[`ses.getAllExtensions()`](session.md#sesgetallextensions).
#### `BrowserWindow.addDevToolsExtension(path)` _Deprecated_
* `path` String
Adds DevTools extension located at `path`, and returns extension's name.
The extension will be remembered so you only need to call this API once, this
API is not for programming use. If you try to add an extension that has already
been loaded, this method will not return and instead log a warning to the
console.
The method will also not return if the extension's manifest is missing or incomplete.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
**Note:** This method is deprecated. Instead, use
[`ses.loadExtension(path)`](session.md#sesloadextensionpath).
#### `BrowserWindow.removeDevToolsExtension(name)` _Deprecated_
* `name` String
Remove a DevTools extension by name.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
**Note:** This method is deprecated. Instead, use
[`ses.removeExtension(extension_id)`](session.md#sesremoveextensionextensionid).
#### `BrowserWindow.getDevToolsExtensions()` _Deprecated_
Returns `Record<string, ExtensionInfo>` - The keys are the extension names and each value is
an Object containing `name` and `version` properties.
To check if a DevTools extension is installed you can run the following:
```javascript
const { BrowserWindow } = require('electron')
const installed = 'devtron' in BrowserWindow.getDevToolsExtensions()
console.log(installed)
```
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
**Note:** This method is deprecated. Instead, use
[`ses.getAllExtensions()`](session.md#sesgetallextensions).
### Instance Properties
Objects created with `new BrowserWindow` have the following properties:

View File

@@ -65,12 +65,12 @@ Forces the maximum disk space to be used by the disk cache, in bytes.
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`
* `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`
### --enable-logging

View File

@@ -16,7 +16,7 @@ const { app, contentTracing } = require('electron')
app.whenReady().then(() => {
(async () => {
await contentTracing.startRecording({
include_categories: ['*']
included_categories: ['*']
})
console.log('Tracing started')
await new Promise(resolve => setTimeout(resolve, 5000))

View File

@@ -44,19 +44,19 @@ The `contextBridge` module has the following methods:
### `contextBridge.exposeInMainWorld(apiKey, api)` _Experimental_
* `apiKey` String - The key to inject the API onto `window` with. The API will be accessible on `window[apiKey]`.
* `api` Record<String, any> - Your API object, more information on what this API can be and how it works is available below.
* `api` any - Your API, more information on what this API can be and how it works is available below.
## Usage
### API Objects
### API
The `api` object provided to [`exposeInMainWorld`](#contextbridgeexposeinmainworldapikey-api-experimental) must be an object
The `api` provided to [`exposeInMainWorld`](#contextbridgeexposeinmainworldapikey-api-experimental) must be a `Function`, `String`, `Number`, `Array`, `Boolean`, or an object
whose keys are strings and values are a `Function`, `String`, `Number`, `Array`, `Boolean`, or another nested object that meets the same conditions.
`Function` values are proxied to the other context and all other values are **copied** and **frozen**. Any data / primitives sent in
the API object become immutable and updates on either side of the bridge do not result in an update on the other side.
the API become immutable and updates on either side of the bridge do not result in an update on the other side.
An example of a complex API object is shown below:
An example of a complex API is shown below:
```javascript
const { contextBridge } = require('electron')

View File

@@ -128,7 +128,7 @@ must be at most 39 bytes long, and values must be no longer than 127 bytes.
Keys with names longer than the maximum will be silently ignored. Key values
longer than the maximum length will be truncated.
**Note:** Calling this method from the renderer process is deprecated.
**Note:** This method is only available in the main process.
### `crashReporter.getLastCrashReport()`
@@ -137,7 +137,7 @@ last crash report. Only crash reports that have been uploaded will be returned;
even if a crash report is present on disk it will not be returned until it is
uploaded. In the case that there are no uploaded reports, `null` is returned.
**Note:** Calling this method from the renderer process is deprecated.
**Note:** This method is only available in the main process.
### `crashReporter.getUploadedReports()`
@@ -146,14 +146,14 @@ Returns [`CrashReport[]`](structures/crash-report.md):
Returns all uploaded crash reports. Each report contains the date and uploaded
ID.
**Note:** Calling this method from the renderer process is deprecated.
**Note:** This method is only available in the main process.
### `crashReporter.getUploadToServer()`
Returns `Boolean` - Whether reports should be submitted to the server. Set through
the `start` method or `setUploadToServer`.
**Note:** Calling this method from the renderer process is deprecated.
**Note:** This method is only available in the main process.
### `crashReporter.setUploadToServer(uploadToServer)`
@@ -162,13 +162,7 @@ the `start` method or `setUploadToServer`.
This would normally be controlled by user preferences. This has no effect if
called before `start` is called.
**Note:** Calling this method from the renderer process is deprecated.
### `crashReporter.getCrashesDirectory()` _Deprecated_
Returns `String` - The directory where crashes are temporarily stored before being uploaded.
**Note:** This method is deprecated, use `app.getPath('crashDumps')` instead.
**Note:** This method is only available in the main process.
### `crashReporter.addExtraParameter(key, value)`

View File

@@ -120,6 +120,24 @@ debugging purposes.
Prints Chrome's internal logging to the console.
### `ELECTRON_DEBUG_DRAG_REGIONS`
Adds coloration to draggable regions on [`BrowserView`](./browser-view.md)s on macOS - draggable regions will be colored
green and non-draggable regions will be colored red to aid debugging.
### `ELECTRON_DEBUG_NOTIFICATIONS`
Adds extra logs to [`Notification`](./notification.md) lifecycles on macOS to aid in debugging. Extra logging will be displayed when new Notifications are created or activated. They will also be displayed when common actions are taken: a notification is shown, dismissed, its button is clicked, or it is replied to.
Sample output:
```sh
Notification created (com.github.Electron:notification:EAF7B87C-A113-43D7-8E76-F88EC9D73D44)
Notification displayed (com.github.Electron:notification:EAF7B87C-A113-43D7-8E76-F88EC9D73D44)
Notification activated (com.github.Electron:notification:EAF7B87C-A113-43D7-8E76-F88EC9D73D44)
Notification replied to (com.github.Electron:notification:EAF7B87C-A113-43D7-8E76-F88EC9D73D44)
```
### `ELECTRON_LOG_ASAR_READS`
When Electron reads from an ASAR file, log the read offset and file path to

View File

@@ -12,28 +12,29 @@ It adds the following events, properties, and methods:
In sandboxed renderers the `process` object contains only a subset of the APIs:
- `crash()`
- `hang()`
- `getCreationTime()`
- `getHeapStatistics()`
- `getBlinkMemoryInfo()`
- `getProcessMemoryInfo()`
- `getSystemMemoryInfo()`
- `getSystemVersion()`
- `getCPUUsage()`
- `getIOCounters()`
- `argv`
- `execPath`
- `env`
- `pid`
- `arch`
- `platform`
- `sandboxed`
- `type`
- `version`
- `versions`
- `mas`
- `windowsStore`
* `crash()`
* `hang()`
* `getCreationTime()`
* `getHeapStatistics()`
* `getBlinkMemoryInfo()`
* `getProcessMemoryInfo()`
* `getSystemMemoryInfo()`
* `getSystemVersion()`
* `getCPUUsage()`
* `getIOCounters()`
* `uptime()`
* `argv`
* `execPath`
* `env`
* `pid`
* `arch`
* `platform`
* `sandboxed`
* `type`
* `version`
* `versions`
* `mas`
* `windowsStore`
## Events

View File

@@ -36,8 +36,8 @@ you can use [webContents.executeJavaScript](web-contents.md#contentsexecutejavas
**Note:** The remote module can be disabled for security reasons in the following contexts:
- [`BrowserWindow`](browser-window.md) - by setting the `enableRemoteModule` option to `false`.
- [`<webview>`](webview-tag.md) - by setting the `enableremotemodule` attribute to `false`.
* [`BrowserWindow`](browser-window.md) - by setting the `enableRemoteModule` option to `false`.
* [`<webview>`](webview-tag.md) - by setting the `enableremotemodule` attribute to `false`.
## Remote Objects

View File

@@ -101,8 +101,8 @@ Returns:
Emitted after an extension is loaded. This occurs whenever an extension is
added to the "enabled" set of extensions. This includes:
- Extensions being loaded from `Session.loadExtension`.
- Extensions being reloaded:
* Extensions being loaded from `Session.loadExtension`.
* Extensions being reloaded:
* from a crash.
* if the extension requested it ([`chrome.runtime.reload()`](https://developer.chrome.com/extensions/runtime#method-reload)).
@@ -500,6 +500,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
* `pointerLock` - Request to directly interpret mouse movements as an input method. Click [here](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API) to know more.
* `fullscreen` - Request for the app to enter fullscreen mode.
* `openExternal` - Request to open links in external applications.
* `unknown` - An unrecognized permission request
* `callback` Function
* `permissionGranted` Boolean - Allow or deny the permission.
* `details` Object - Some properties are only available on certain permission types.
@@ -511,7 +512,9 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
Sets the handler which can be used to respond to permission requests for the `session`.
Calling `callback(true)` will allow the permission and `callback(false)` will reject it.
To clear the handler, call `setPermissionRequestHandler(null)`.
To clear the handler, call `setPermissionRequestHandler(null)`. Please note that
you must also implement `setPermissionCheckHandler` to get complete permission handling.
Most web APIs do a permission check and then make a permission request if the check is denied.
```javascript
const { session } = require('electron')
@@ -527,28 +530,32 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
#### `ses.setPermissionCheckHandler(handler)`
* `handler` Function\<Boolean> | null
* `webContents` [WebContents](web-contents.md) - WebContents checking the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin.
* `webContents` ([WebContents](web-contents.md) | null) - WebContents checking the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin. Cross origin sub frames making permission checks will pass a `null` webContents to this handler. You should use `embeddingOrigin` and `requestingOrigin` to determine what origin the owning frame and the requesting frame are on respectively.
* `permission` String - Type of permission check. Valid values are `midiSysex`, `notifications`, `geolocation`, `media`,`mediaKeySystem`,`midi`, `pointerLock`, `fullscreen`, `openExternal`, or `serial`.
* `requestingOrigin` String - The origin URL of the permission check
* `details` Object - Some properties are only available on certain permission types.
* `securityOrigin` String - The security origin of the `media` check.
* `mediaType` String - The type of media access being requested, can be `video`,
* `embeddingOrigin` String (optional) - The origin of the frame embedding the frame that made the permission check. Only set for cross-origin sub frames making permission checks.
* `securityOrigin` String (optional) - The security origin of the `media` check.
* `mediaType` String (optional) - The type of media access being requested, can be `video`,
`audio` or `unknown`
* `requestingUrl` String - The last URL the requesting frame loaded
* `requestingUrl` String (optional) - The last URL the requesting frame loaded. This is not provided for cross-origin sub frames making permission checks.
* `isMainFrame` Boolean - Whether the frame making the request is the main frame
Sets the handler which can be used to respond to permission checks for the `session`.
Returning `true` will allow the permission and `false` will reject it.
Returning `true` will allow the permission and `false` will reject it. Please note that
you must also implement `setPermissionRequestHandler` to get complete permission handling.
Most web APIs do a permission check and then make a permission request if the check is denied.
To clear the handler, call `setPermissionCheckHandler(null)`.
```javascript
const { session } = require('electron')
session.fromPartition('some-partition').setPermissionCheckHandler((webContents, permission) => {
if (webContents.getURL() === 'some-host' && permission === 'notifications') {
return false // denied
const url = require('url')
session.fromPartition('some-partition').setPermissionCheckHandler((webContents, permission, requestingOrigin) => {
if (new URL(requestingOrigin).hostname === 'some-host' && permission === 'notifications') {
return true // granted
}
return true
return false // denied
})
```

View File

@@ -45,17 +45,6 @@ Returns `Promise<void>`
Open the given external protocol URL in the desktop's default manner. (For example, mailto: URLs in the user's default mail agent).
### `shell.moveItemToTrash(fullPath[, deleteOnFail])` _Deprecated_
* `fullPath` String
* `deleteOnFail` Boolean (optional) - Whether or not to unilaterally remove the item if the Trash is disabled or unsupported on the volume. _macOS_
Returns `Boolean` - Whether the item was successfully moved to the trash or otherwise deleted.
> NOTE: This method is deprecated. Use `shell.trashItem` instead.
Move the given file to trash and returns a boolean status for the operation.
### `shell.trashItem(path)`
* `path` String - path to the item to be moved to the trash.

View File

@@ -433,7 +433,7 @@ It will always return `granted` for `screen` and for all media types on older ve
Returns `Promise<Boolean>` - A promise that resolves with `true` if consent was granted and `false` if it was denied. If an invalid `mediaType` is passed, the promise will be rejected. If an access request was denied and later is changed through the System Preferences pane, a restart of the app will be required for the new permissions to take effect. If access has already been requested and denied, it _must_ be changed through the preference pane; an alert will not pop up and the promise will resolve with the existing access status.
**Important:** In order to properly leverage this API, you [must set](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos?language=objc) the `NSMicrophoneUsageDescription` and `NSCameraUsageDescription` strings in your app's `Info.plist` file. The values for these keys will be used to populate the permission dialogs so that the user will be properly informed as to the purpose of the permission request. See [Electron Application Distribution](https://electronjs.org/docs/tutorial/application-distribution#macos) for more information about how to set these in the context of Electron.
**Important:** In order to properly leverage this API, you [must set](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos?language=objc) the `NSMicrophoneUsageDescription` and `NSCameraUsageDescription` strings in your app's `Info.plist` file. The values for these keys will be used to populate the permission dialogs so that the user will be properly informed as to the purpose of the permission request. See [Electron Application Distribution](../tutorial/application-distribution.md#macos) for more information about how to set these in the context of Electron.
This user consent was not required until macOS 10.14 Mojave, so this method will always return `true` if your system is running 10.13 High Sierra or lower.

View File

@@ -42,7 +42,8 @@ returns `null`.
* `id` Integer
Returns `WebContents` - A WebContents instance with the given ID.
Returns `WebContents` | undefined - A WebContents instance with the given ID, or
`undefined` if there is no WebContents associated with the given ID.
## Class: WebContents
@@ -155,7 +156,7 @@ Returns:
be set. If no post data is to be sent, the value will be `null`. Only defined
when the window is being created by a form that set `target=_blank`.
Deprecated in favor of [`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandler-handler).
Deprecated in favor of [`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandlerhandler).
Emitted when the page requests to open a new window for a `url`. It could be
requested by `window.open` or an external link like `<a target='_blank'>`.
@@ -194,33 +195,34 @@ myBrowserWindow.webContents.on('new-window', (event, url, frameName, disposition
#### Event: 'did-create-window'
Returns:
* `window` BrowserWindow
* `details` Object
* `url` String - URL for the created window.
* `frameName` String - Name given to the created window in the
`window.open()` call.
* `options` BrowserWindowConstructorOptions - The options used to create the
BrowserWindow. They are merged in increasing precedence: options inherited
from the parent, parsed options from the `features` string from
`window.open()`, and options given by
[`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandler-handler).
Unrecognized options are not filtered out.
* `additionalFeatures` String[] - The non-standard features (features not
handled Chromium or Electron) _Deprecated_
* `referrer` [Referrer](structures/referrer.md) - The referrer that will be
passed to the new window. May or may not result in the `Referer` header
being sent, depending on the referrer policy.
* `postBody` [PostBody](structures/post-body.md) (optional) - The post data
that will be sent to the new window, along with the appropriate headers
that will be set. If no post data is to be sent, the value will be `null`.
Only defined when the window is being created by a form that set
`target=_blank`.
* `disposition` String - Can be `default`, `foreground-tab`,
`background-tab`, `new-window`, `save-to-disk` and `other`.
* `url` String - URL for the created window.
* `frameName` String - Name given to the created window in the
`window.open()` call.
* `options` BrowserWindowConstructorOptions - The options used to create the
BrowserWindow. They are merged in increasing precedence: options inherited
from the parent, parsed options from the `features` string from
`window.open()`, and options given by
[`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandlerhandler).
Unrecognized options are not filtered out.
* `additionalFeatures` String[] - The non-standard features (features not
handled Chromium or Electron) _Deprecated_
* `referrer` [Referrer](structures/referrer.md) - The referrer that will be
passed to the new window. May or may not result in the `Referer` header
being sent, depending on the referrer policy.
* `postBody` [PostBody](structures/post-body.md) (optional) - The post data
that will be sent to the new window, along with the appropriate headers
that will be set. If no post data is to be sent, the value will be `null`.
Only defined when the window is being created by a form that set
`target=_blank`.
* `disposition` String - Can be `default`, `foreground-tab`,
`background-tab`, `new-window`, `save-to-disk` and `other`.
Emitted _after_ successful creation of a window via `window.open` in the renderer.
Not emitted if the creation of the window is canceled from
[`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandler-handler).
[`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandlerhandler).
See [`window.open()`](window-open.md) for more details and how to use this in conjunction with `webContents.setWindowOpenHandler`.
@@ -1463,7 +1465,7 @@ By default, an empty `options` will be regarded as:
}
```
Use `page-break-before: always; ` CSS style to force to print to a new page.
Use `page-break-before: always;` CSS style to force to print to a new page.
An example of `webContents.printToPDF`:
@@ -1869,7 +1871,7 @@ Returns `Boolean` - If *offscreen rendering* is enabled returns whether it is cu
* `fps` Integer
If *offscreen rendering* is enabled sets the frame rate to the specified number.
Only values between 1 and 60 are accepted.
Only values between 1 and 240 are accepted.
#### `contents.getFrameRate()`
@@ -1967,7 +1969,7 @@ The zoom factor is the zoom percent divided by 100, so 300% = 3.0.
#### `contents.frameRate`
An `Integer` property that sets the frame rate of the web contents to the specified number.
Only values between 1 and 60 are accepted.
Only values between 1 and 240 are accepted.
Only applicable if *offscreen rendering* is enabled.

View File

@@ -3,8 +3,8 @@
There are several ways to control how windows are created from trusted or
untrusted content within a renderer. Windows can be created from the renderer in two ways:
- clicking on links or submitting forms adorned with `target=_blank`
- JavaScript calling `window.open()`
* clicking on links or submitting forms adorned with `target=_blank`
* JavaScript calling `window.open()`
In non-sandboxed renderers, or when `nativeWindowOpen` is false (the default), this results in the creation of a
[`BrowserWindowProxy`](browser-window-proxy.md), a light wrapper around
@@ -26,7 +26,7 @@ BrowserWindow constructor options are set by, in increasing precedence
order: options inherited from the parent, parsed options
from the `features` string from `window.open()`, security-related webPreferences
inherited from the parent, and options given by
[`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandler-handler).
[`webContents.setWindowOpenHandler`](web-contents.md#contentssetwindowopenhandlerhandler).
Note that `webContents.setWindowOpenHandler` has final say and full privilege
because it is invoked in the main process.

View File

@@ -6,14 +6,36 @@ Breaking changes will be documented here, and deprecation warnings added to JS c
This document uses the following convention to categorize breaking changes:
- **API Changed:** An API was changed in such a way that code that has not been updated is guaranteed to throw an exception.
- **Behavior Changed:** The behavior of Electron has changed, but not in such a way that an exception will necessarily be thrown.
- **Default Changed:** Code depending on the old default may break, not necessarily throwing an exception. The old behavior can be restored by explicitly specifying the value.
- **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
- **Removed:** An API or feature was removed, and is no longer supported by Electron.
* **API Changed:** An API was changed in such a way that code that has not been updated is guaranteed to throw an exception.
* **Behavior Changed:** The behavior of Electron has changed, but not in such a way that an exception will necessarily be thrown.
* **Default Changed:** Code depending on the old default may break, not necessarily throwing an exception. The old behavior can be restored by explicitly specifying the value.
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
## Planned Breaking API Changes (13.0)
### API Changed: `session.setPermissionCheckHandler(handler)`
The `handler` methods first parameter was previously always a `webContents`, it can now sometimes be `null`. You should use the `requestingOrigin`, `embeddingOrigin` and `securityOrigin` properties to respond to the permission check correctly. As the `webContents` can be `null` it can no longer be relied on.
```js
// Old code
session.setPermissionCheckHandler((webContents, permission) => {
if (webContents.getURL().startsWith('https://google.com/') && permission === 'notification') {
return true
}
return false
})
// Replace with
session.setPermissionCheckHandler((webContents, permission, requestingOrigin) => {
if (new URL(requestingOrigin).hostname === 'google.com' && permission === 'notification') {
return true
}
return false
})
```
### Removed: `shell.moveItemToTrash()`
The deprecated synchronous `shell.moveItemToTrash()` API has been removed. Use
@@ -26,6 +48,47 @@ shell.moveItemToTrash(path)
shell.trashItem(path).then(/* ... */)
```
### Removed: `BrowserWindow` extension APIs
The deprecated extension APIs have been removed:
* `BrowserWindow.addExtension(path)`
* `BrowserWindow.addDevToolsExtension(path)`
* `BrowserWindow.removeExtension(name)`
* `BrowserWindow.removeDevToolsExtension(name)`
* `BrowserWindow.getExtensions()`
* `BrowserWindow.getDevToolsExtensions()`
Use the session APIs instead:
* `ses.loadExtension(path)`
* `ses.removeExtension(extension_id)`
* `ses.getAllExtensions()`
```js
// Removed in Electron 13
BrowserWindow.addExtension(path)
BrowserWindow.addDevToolsExtension(path)
// Replace with
session.defaultSession.loadExtension(path)
```
```js
// Removed in Electron 13
BrowserWindow.removeExtension(name)
BrowserWindow.removeDevToolsExtension(name)
// Replace with
session.defaultSession.removeExtension(extension_id)
```
```js
// Removed in Electron 13
BrowserWindow.getExtensions()
BrowserWindow.getDevToolsExtensions()
// Replace with
session.defaultSession.getAllExtensions()
```
## Planned Breaking API Changes (12.0)
### Removed: Pepper Flash support
@@ -43,17 +106,29 @@ We [recommend having contextIsolation enabled](https://github.com/electron/elect
For more details see: https://github.com/electron/electron/issues/23506
### Removed: `crashReporter.getCrashesDirectory()`
The `crashReporter.getCrashesDirectory` method has been removed. Usage
should be replaced by `app.getPath('crashDumps')`.
```js
// Removed in Electron 12
crashReporter.getCrashesDirectory()
// Replace with
app.getPath('crashDumps')
```
### Removed: `crashReporter` methods in the renderer process
The following `crashReporter` methods are no longer available in the renderer
process:
- `crashReporter.start`
- `crashReporter.getLastCrashReport`
- `crashReporter.getUploadedReports`
- `crashReporter.getUploadToServer`
- `crashReporter.setUploadToServer`
- `crashReporter.getCrashesDirectory`
* `crashReporter.start`
* `crashReporter.getLastCrashReport`
* `crashReporter.getUploadedReports`
* `crashReporter.getUploadToServer`
* `crashReporter.setUploadToServer`
* `crashReporter.getCrashesDirectory`
They should be called only from the main process.
@@ -104,6 +179,7 @@ shell.trashItem(path).then(/* ... */)
## Planned Breaking API Changes (11.0)
### Removed: `BrowserView.{destroy, fromId, fromWebContents, getAllViews}` and `id` property of `BrowserView`
The experimental APIs `BrowserView.{destroy, fromId, fromWebContents, getAllViews}`
have now been removed. Additionally, the `id` property of `BrowserView`
has also been removed.
@@ -143,12 +219,12 @@ app.getPath('crashDumps')
Calling the following `crashReporter` methods from the renderer process is
deprecated:
- `crashReporter.start`
- `crashReporter.getLastCrashReport`
- `crashReporter.getUploadedReports`
- `crashReporter.getUploadToServer`
- `crashReporter.setUploadToServer`
- `crashReporter.getCrashesDirectory`
* `crashReporter.start`
* `crashReporter.getLastCrashReport`
* `crashReporter.getUploadedReports`
* `crashReporter.getUploadToServer`
* `crashReporter.setUploadToServer`
* `crashReporter.getCrashesDirectory`
The only non-deprecated methods remaining in the `crashReporter` module in the
renderer are `addExtraParameter`, `removeExtraParameter` and `getParameters`.
@@ -190,6 +266,7 @@ We [recommend moving away from the remote
module](https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31).
### `protocol.unregisterProtocol`
### `protocol.uninterceptProtocol`
The APIs are now synchronous and the optional callback is no longer needed.
@@ -202,14 +279,23 @@ protocol.unregisterProtocol(scheme)
```
### `protocol.registerFileProtocol`
### `protocol.registerBufferProtocol`
### `protocol.registerStringProtocol`
### `protocol.registerHttpProtocol`
### `protocol.registerStreamProtocol`
### `protocol.interceptFileProtocol`
### `protocol.interceptStringProtocol`
### `protocol.interceptBufferProtocol`
### `protocol.interceptHttpProtocol`
### `protocol.interceptStreamProtocol`
The APIs are now synchronous and the optional callback is no longer needed.
@@ -251,6 +337,47 @@ you should plan to update your native modules to be context aware.
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
### Deprecated: `BrowserWindow` extension APIs
The following extension APIs have been deprecated:
* `BrowserWindow.addExtension(path)`
* `BrowserWindow.addDevToolsExtension(path)`
* `BrowserWindow.removeExtension(name)`
* `BrowserWindow.removeDevToolsExtension(name)`
* `BrowserWindow.getExtensions()`
* `BrowserWindow.getDevToolsExtensions()`
Use the session APIs instead:
* `ses.loadExtension(path)`
* `ses.removeExtension(extension_id)`
* `ses.getAllExtensions()`
```js
// Deprecated in Electron 9
BrowserWindow.addExtension(path)
BrowserWindow.addDevToolsExtension(path)
// Replace with
session.defaultSession.loadExtension(path)
```
```js
// Deprecated in Electron 9
BrowserWindow.removeExtension(name)
BrowserWindow.removeDevToolsExtension(name)
// Replace with
session.defaultSession.removeExtension(extension_id)
```
```js
// Deprecated in Electron 9
BrowserWindow.getExtensions()
BrowserWindow.getDevToolsExtensions()
// Replace with
session.defaultSession.getAllExtensions()
```
### Removed: `<webview>.getWebContents()`
This API, which was deprecated in Electron 8.0, is now removed.
@@ -303,7 +430,7 @@ Clone Algorithm][SCA], the same algorithm used to serialize messages for
`postMessage`. This brings about a 2x performance improvement for large
messages, but also brings some breaking changes in behavior.
- Sending Functions, Promises, WeakMaps, WeakSets, or objects containing any
* Sending Functions, Promises, WeakMaps, WeakSets, or objects containing any
such values, over IPC will now throw an exception, instead of silently
converting the functions to `undefined`.
@@ -317,21 +444,21 @@ ipcRenderer.send('channel', { value: 3, someFunction: () => {} })
// => throws Error("() => {} could not be cloned.")
```
- `NaN`, `Infinity` and `-Infinity` will now be correctly serialized, instead
* `NaN`, `Infinity` and `-Infinity` will now be correctly serialized, instead
of being converted to `null`.
- Objects containing cyclic references will now be correctly serialized,
* Objects containing cyclic references will now be correctly serialized,
instead of being converted to `null`.
- `Set`, `Map`, `Error` and `RegExp` values will be correctly serialized,
* `Set`, `Map`, `Error` and `RegExp` values will be correctly serialized,
instead of being converted to `{}`.
- `BigInt` values will be correctly serialized, instead of being converted to
* `BigInt` values will be correctly serialized, instead of being converted to
`null`.
- Sparse arrays will be serialized as such, instead of being converted to dense
* Sparse arrays will be serialized as such, instead of being converted to dense
arrays with `null`s.
- `Date` objects will be transferred as `Date` objects, instead of being
* `Date` objects will be transferred as `Date` objects, instead of being
converted to their ISO string representation.
- Typed Arrays (such as `Uint8Array`, `Uint16Array`, `Uint32Array` and so on)
* Typed Arrays (such as `Uint8Array`, `Uint16Array`, `Uint32Array` and so on)
will be transferred as such, instead of being converted to Node.js `Buffer`.
- Node.js `Buffer` objects will be transferred as `Uint8Array`s. You can
* Node.js `Buffer` objects will be transferred as `Uint8Array`s. You can
convert a `Uint8Array` back to a Node.js `Buffer` by wrapping the underlying
`ArrayBuffer`:

View File

@@ -86,8 +86,6 @@ $ gclient sync -f
```sh
$ cd src
$ export CHROMIUM_BUILDTOOLS_PATH=`pwd`/buildtools
# this next line is needed only if building with sccache
$ export GN_EXTRA_ARGS="${GN_EXTRA_ARGS} cc_wrapper=\"${PWD}/electron/external_binaries/sccache\""
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\") $GN_EXTRA_ARGS"
```
@@ -141,12 +139,6 @@ This will build all of what was previously 'libchromiumcontent' (i.e. the
`content/` directory of `chromium` and its dependencies, incl. WebKit and V8),
so it will take a while.
To speed up subsequent builds, you can use [sccache][sccache]. Add the GN arg
`cc_wrapper = "sccache"` by running `gn args out/Testing` to bring up an
editor and adding a line to the end of the file.
[sccache]: https://github.com/mozilla/sccache
The built executable will be under `./out/Testing`:
```sh
@@ -189,7 +181,6 @@ Not all combinations of source and target CPU/OS are supported by Chromium.
| Windows x64 | Windows x86 | Automatically tested |
| Linux x64 | Linux x86 | Automatically tested |
If you test other combinations and find them to work, please update this document :)
See the GN reference for allowable values of [`target_os`][target_os values]

View File

@@ -66,11 +66,11 @@ formatted correctly.
Electron APIs uses the same capitalization scheme as Node.js:
- When the module itself is a class like `BrowserWindow`, use `PascalCase`.
- When the module is a set of APIs, like `globalShortcut`, use `camelCase`.
- When the API is a property of object, and it is complex enough to be in a
* When the module itself is a class like `BrowserWindow`, use `PascalCase`.
* When the module is a set of APIs, like `globalShortcut`, use `camelCase`.
* When the API is a property of object, and it is complex enough to be in a
separate chapter like `win.webContents`, use `mixedCase`.
- For other non-module APIs, use natural titles, like `<webview> Tag` or
* For other non-module APIs, use natural titles, like `<webview> Tag` or
`Process Object`.
When creating a new API, it is preferred to use getters and setters instead of

View File

@@ -36,9 +36,9 @@ $ git fetch upstream
Build steps and dependencies differ slightly depending on your operating system.
See these detailed guides on building Electron locally:
* [Building on macOS](https://electronjs.org/docs/development/build-instructions-macos)
* [Building on Linux](https://electronjs.org/docs/development/build-instructions-linux)
* [Building on Windows](https://electronjs.org/docs/development/build-instructions-windows)
* [Building on macOS](build-instructions-macos.md)
* [Building on Linux](build-instructions-linux.md)
* [Building on Windows](build-instructions-windows.md)
Once you've built the project locally, you're ready to start making changes!
@@ -63,7 +63,7 @@ or tests in the `spec/` folder.
Please be sure to run `npm run lint` from time to time on any code changes
to ensure that they follow the project's code style.
See [coding style](https://electronjs.org/docs/development/coding-style) for
See [coding style](coding-style.md) for
more information about best practice when modifying code in different parts of
the project.
@@ -91,29 +91,29 @@ Before a pull request can be merged, it **must** have a pull request title with
Examples of commit messages with semantic prefixes:
- `fix: don't overwrite prevent_default if default wasn't prevented`
- `feat: add app.isPackaged() method`
- `docs: app.isDefaultProtocolClient is now available on Linux`
* `fix: don't overwrite prevent_default if default wasn't prevented`
* `feat: add app.isPackaged() method`
* `docs: app.isDefaultProtocolClient is now available on Linux`
Common prefixes:
- fix: A bug fix
- feat: A new feature
- docs: Documentation changes
- test: Adding missing tests or correcting existing tests
- build: Changes that affect the build system
- ci: Changes to our CI configuration files and scripts
- perf: A code change that improves performance
- refactor: A code change that neither fixes a bug nor adds a feature
- style: Changes that do not affect the meaning of the code (linting)
- vendor: Bumping a dependency like libchromiumcontent or node
* fix: A bug fix
* feat: A new feature
* docs: Documentation changes
* test: Adding missing tests or correcting existing tests
* build: Changes that affect the build system
* ci: Changes to our CI configuration files and scripts
* perf: A code change that improves performance
* refactor: A code change that neither fixes a bug nor adds a feature
* style: Changes that do not affect the meaning of the code (linting)
* vendor: Bumping a dependency like libchromiumcontent or node
Other things to keep in mind when writing a commit message:
1. The first line should:
- contain a short description of the change (preferably 50 characters or less,
* contain a short description of the change (preferably 50 characters or less,
and no more than 72 characters)
- be entirely in lowercase with the exception of proper nouns, acronyms, and
* be entirely in lowercase with the exception of proper nouns, acronyms, and
the words that refer to code, like function/variable names
2. Keep the second line blank.
3. Wrap all other lines at 72 columns.
@@ -144,7 +144,7 @@ master.
### Step 7: Test
Bug fixes and features should always come with tests. A
[testing guide](https://electronjs.org/docs/development/testing) has been
[testing guide](testing.md) has been
provided to make the process easier. Looking at other tests to see how they
should be structured can also help.

View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
<a href="#" id="drag">Drag me</a>
<script src="renderer.js"></script>
</body>
</html>

View File

@@ -0,0 +1,41 @@
const { app, BrowserWindow, ipcMain, nativeImage, NativeImage } = require('electron')
const fs = require('fs');
const http = require('http');
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
const iconName = 'iconForDragAndDrop.png';
const icon = fs.createWriteStream(`${process.cwd()}/${iconName}`);
http.get('http://img.icons8.com/ios/452/drag-and-drop.png', (response) => {
response.pipe(icon);
});
app.whenReady().then(createWindow)
ipcMain.on('ondragstart', (event, filePath) => {
event.sender.startDrag({
file: filePath,
icon: `${process.cwd()}/${iconName}`
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,9 @@
const { ipcRenderer } = require('electron')
const fs = require('fs')
document.getElementById('drag').ondragstart = (event) => {
const fileName = 'drag-and-drop.md'
fs.writeFileSync(fileName, '# Test drag and drop');
event.preventDefault()
ipcRenderer.send('ondragstart', process.cwd() + `/${fileName}`)
}

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,31 @@
const { app, BrowserWindow, globalShortcut } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
globalShortcut.register('Alt+CommandOrControl+I', () => {
console.log('Electron loves global shortcuts!')
})
}).then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</body>
</html>

View File

@@ -0,0 +1,13 @@
const { app, BrowserWindow } = require('electron')
app.whenReady().then(() => {
const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } })
win.loadFile('index.html')
win.webContents.on('before-input-event', (event, input) => {
if (input.control && input.key.toLowerCase() === 'i') {
console.log('Pressed Control+I')
event.preventDefault()
}
})
})

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,39 @@
const { app, BrowserWindow, Menu, MenuItem } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
const menu = new Menu()
menu.append(new MenuItem({
label: 'Electron',
submenu: [{
role: 'help',
accelerator: process.platform === 'darwin' ? 'Alt+Cmd+I' : 'Alt+Shift+I',
click: () => { console.log('Electron rocks!') }
}]
}))
Menu.setApplicationMenu(menu)
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
<h1>Hello World!</h1>
<p>Current theme source: <strong id="theme-source">System</strong></p>
<button id="toggle-dark-mode">Toggle Dark Mode</button>
<button id="reset-to-system">Reset to System Theme</button>
<script src="renderer.js"></script>
</body>
</body>
</html>

View File

@@ -0,0 +1,40 @@
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
ipcMain.handle('dark-mode:toggle', () => {
if (nativeTheme.shouldUseDarkColors) {
nativeTheme.themeSource = 'light'
} else {
nativeTheme.themeSource = 'dark'
}
return nativeTheme.shouldUseDarkColors
})
ipcMain.handle('dark-mode:system', () => {
nativeTheme.themeSouce = 'system'
})
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,11 @@
const { ipcRenderer } = require('electron')
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
const isDarkMode = await ipcRenderer.invoke('dark-mode:toggle')
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
})
document.getElementById('reset-to-system').addEventListener('click', async () => {
await ipcRenderer.invoke('dark-mode:system')
document.getElementById('theme-source').innerHTML = 'System'
})

View File

@@ -0,0 +1,7 @@
@media (prefers-color-scheme: dark) {
body { background: #333; color: white; }
}
@media (prefers-color-scheme: light) {
body { background: #ddd; color: black; }
}

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,43 @@
const { app, BrowserWindow, Menu } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
const dockMenu = Menu.buildFromTemplate([
{
label: 'New Window',
click () { console.log('New Window') }
}, {
label: 'New Window with Settings',
submenu: [
{ label: 'Basic' },
{ label: 'Pro' }
]
},
{ label: 'New Command...' }
])
app.whenReady().then(() => {
app.dock.setMenu(dockMenu)
}).then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,35 @@
const { app, BrowserWindow, Notification } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
function showNotification () {
const notification = {
title: 'Basic Notification',
body: 'Notification from the Main process'
}
new Notification(notification).show()
}
app.whenReady().then(createWindow).then(showNotification)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
<script src="renderer.js"></script>
</body>
</html>

View File

@@ -0,0 +1,27 @@
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,7 @@
const myNotification = new Notification('Title', {
body: 'Notification from the Renderer process'
})
myNotification.onclick = () => {
console.log('Notification clicked')
}

View File

@@ -0,0 +1,15 @@
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,28 @@
const { app, BrowserWindow } = require('electron')
const fs = require('fs')
app.disableHardwareAcceleration()
let win
app.whenReady().then(() => {
win = new BrowserWindow({ webPreferences: { offscreen: true } })
win.loadURL('https://github.com')
win.webContents.on('paint', (event, dirty, image) => {
fs.writeFileSync('ex.png', image.toPNG())
})
win.webContents.setFrameRate(60)
console.log(`The screenshot has been successfully saved to ${process.cwd()}/ex.png`)
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
<script src="renderer.js"></script>
</body>
</html>

View File

@@ -0,0 +1,24 @@
const { app, BrowserWindow, ipcMain } = require('electron')
let onlineStatusWindow
app.whenReady().then(() => {
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false, webPreferences: { nodeIntegration: true } })
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
})
ipcMain.on('online-status-changed', (event, status) => {
console.log(status)
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,7 @@
const { ipcRenderer } = require('electron')
const updateOnlineStatus = () => { ipcRenderer.send('online-status-changed', navigator.onLine ? 'online' : 'offline') }
window.addEventListener('online', updateOnlineStatus)
window.addEventListener('offline', updateOnlineStatus)
updateOnlineStatus()

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
<script src="renderer.js"></script>
</body>
</html>

View File

@@ -0,0 +1,20 @@
const { app, BrowserWindow } = require('electron')
let onlineStatusWindow
app.whenReady().then(() => {
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false })
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,6 @@
const alertOnlineStatus = () => { window.alert(navigator.onLine ? 'online' : 'offline') }
window.addEventListener('online', alertOnlineStatus)
window.addEventListener('offline', alertOnlineStatus)
alertOnlineStatus()

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,30 @@
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
win.setProgressBar(0.5)
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,34 @@
const { app, BrowserWindow } = require('electron')
const fs = require('fs')
const path = require('path')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
const fileName = 'recently-used.md'
fs.writeFile(fileName, 'Lorem Ipsum', () => {
app.addRecentDocument(path.join(process.cwd(), `${fileName}`))
})
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
app.clearRecentDocuments()
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,33 @@
const { app, BrowserWindow } = require('electron')
const os = require('os');
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
const win = new BrowserWindow()
win.setRepresentedFilename(os.homedir())
win.setDocumentEdited(true)
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>

View File

@@ -0,0 +1,27 @@
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -49,6 +49,7 @@ For API references, there are exceptions to this rule.
* No nesting lists more than 2 levels (due to the markdown renderer).
* All `js` and `javascript` code blocks are linted with
[standard-markdown](https://www.npmjs.com/package/standard-markdown).
* For unordered lists, use asterisks instead of dashes
## Picking words

View File

@@ -43,6 +43,6 @@ If the V8 context crashes, the DevTools will display this message.
`DevTools was disconnected from the page. Once page is reloaded, DevTools will automatically reconnect.`
Chromium logs can be enabled via the `ELECTRON_ENABLE_LOGGING` environment variable. For more information, see the [environment variables documentation](https://www.electronjs.org/docs/api/environment-variables#electron_enable_logging).
Chromium logs can be enabled via the `ELECTRON_ENABLE_LOGGING` environment variable. For more information, see the [environment variables documentation](../api/environment-variables.md#electron_enable_logging).
Alternatively, the command line argument `--enable-logging` can be passed. More information is available in the [command line switches documentation](https://www.electronjs.org/docs/api/command-line-switches#--enable-logging).
Alternatively, the command line argument `--enable-logging` can be passed. More information is available in the [command line switches documentation](../api/command-line-switches.md#--enable-logging).

View File

@@ -1,25 +1,38 @@
# Application Distribution
To distribute your app with Electron, you need to package and rebrand it. The easiest way to do this is to use one of the following third party packaging tools:
## Overview
To distribute your app with Electron, you need to package and rebrand it.
To do this, you can either use specialized tooling or manual approaches.
## With tooling
You can use the following tools to distribute your application:
* [electron-forge](https://github.com/electron-userland/electron-forge)
* [electron-builder](https://github.com/electron-userland/electron-builder)
* [electron-packager](https://github.com/electron/electron-packager)
These tools will take care of all the steps you need to take to end up with a distributable Electron applications, such as packaging your application, rebranding the executable, setting the right icons and optionally creating installers.
These tools will take care of all the steps you need to take to end up with a
distributable Electron application, such as bundling your application,
rebranding the executable, and setting the right icons.
You can check the example of how to package your app with `electron-forge` in
our [Quick Start Guide](quick-start.md#package-and-distribute-the-application).
## Manual distribution
You can also choose to manually get your app ready for distribution. The steps needed to do this are outlined below.
### With prebuilt binaries
To distribute your app with Electron, you need to download Electron's [prebuilt
To distribute your app manually, you need to download Electron's [prebuilt
binaries](https://github.com/electron/electron/releases). Next, the folder
containing your app should be named `app` and placed in Electron's resources
directory as shown in the following examples. Note that the location of
Electron's prebuilt binaries is indicated with `electron/` in the examples
below.
directory as shown in the following examples.
On macOS:
> *NOTE:* the location of Electron's prebuilt binaries is indicated
with `electron/` in the examples below.
*On macOS:*
```plaintext
electron/Electron.app/Contents/Resources/app/
@@ -28,7 +41,7 @@ electron/Electron.app/Contents/Resources/app/
└── index.html
```
On Windows and Linux:
*On Windows and Linux:*
```plaintext
electron/resources/app
@@ -37,47 +50,44 @@ electron/resources/app
└── index.html
```
Then execute `Electron.app` (or `electron` on Linux, `electron.exe` on Windows),
and Electron will start as your app. The `electron` directory will then be
your distribution to deliver to final users.
Then execute `Electron.app` on macOS, `electron` on Linux, or `electron.exe`
on Windows, and Electron will start as your app. The `electron` directory
will then be your distribution to deliver to users.
## Packaging Your App into a File
### With an app source code archive
Apart from shipping your app by copying all of its source files, you can also
package your app into an [asar](https://github.com/electron/asar) archive to avoid
exposing your app's source code to users.
Instead of from shipping your app by copying all of its source files, you can
package your app into an [asar] archive to improve the performance of reading
files on platforms like Windows, if you are not already using a bundler such
as Parcel or Webpack.
To use an `asar` archive to replace the `app` folder, you need to rename the
archive to `app.asar`, and put it under Electron's resources directory like
below, and Electron will then try to read the archive and start from it.
On macOS:
*On macOS:*
```plaintext
electron/Electron.app/Contents/Resources/
└── app.asar
```
On Windows and Linux:
*On Windows and Linux:*
```plaintext
electron/resources/
└── app.asar
```
More details can be found in [Application packaging](application-packaging.md).
You can find more details on how to use `asar` in the
[`electron/asar` repository][asar].
## Rebranding with Downloaded Binaries
### Rebranding with downloaded binaries
After bundling your app into Electron, you will want to rebrand Electron
before distributing it to users.
### Windows
You can rename `electron.exe` to any name you like, and edit its icon and other
information with tools like [rcedit](https://github.com/electron/rcedit).
### macOS
#### macOS
You can rename `Electron.app` to any name you want, and you also have to rename
the `CFBundleDisplayName`, `CFBundleIdentifier` and `CFBundleName` fields in the
@@ -104,60 +114,20 @@ MyApp.app/Contents
   └── MyApp Helper
```
### Linux
#### Windows
You can rename `electron.exe` to any name you like, and edit its icon and other
information with tools like [rcedit](https://github.com/electron/rcedit).
#### Linux
You can rename the `electron` executable to any name you like.
## Rebranding by Rebuilding Electron from Source
### Rebranding by rebuilding Electron from source
It is also possible to rebrand Electron by changing the product name and
building it from source. To do this you need to set the build argument
corresponding to the product name (`electron_product_name = "YourProductName"`)
in the `args.gn` file and rebuild.
### Creating a Custom Electron Fork
Creating a custom fork of Electron is almost certainly not something you will
need to do in order to build your app, even for "Production Level" applications.
Using a tool such as `electron-packager` or `electron-forge` will allow you to
"Rebrand" Electron without having to do these steps.
You need to fork Electron when you have custom C++ code that you have patched
directly into Electron, that either cannot be upstreamed, or has been rejected
from the official version. As maintainers of Electron, we very much would like
to make your scenario work, so please try as hard as you can to get your changes
into the official version of Electron, it will be much much easier on you, and
we appreciate your help.
#### Creating a Custom Release with surf-build
1. Install [Surf](https://github.com/surf-build/surf), via npm:
`npm install -g surf-build@latest`
2. Create a new S3 bucket and create the following empty directory structure:
```sh
- electron/
- symbols/
- dist/
```
3. Set the following Environment Variables:
* `ELECTRON_GITHUB_TOKEN` - a token that can create releases on GitHub
* `ELECTRON_S3_ACCESS_KEY`, `ELECTRON_S3_BUCKET`, `ELECTRON_S3_SECRET_KEY` -
the place where you'll upload Node.js headers as well as symbols
* `ELECTRON_RELEASE` - Set to `true` and the upload part will run, leave unset
and `surf-build` will do CI-type checks, appropriate to run for every
pull request.
* `CI` - Set to `true` or else it will fail
* `GITHUB_TOKEN` - set it to the same as `ELECTRON_GITHUB_TOKEN`
* `SURF_TEMP` - set to `C:\Temp` on Windows to prevent path too long issues
* `TARGET_ARCH` - set to `ia32` or `x64`
4. In `script/upload.py`, you _must_ set `ELECTRON_REPO` to your fork (`MYORG/electron`),
especially if you are a contributor to Electron proper.
5. `surf-build -r https://github.com/MYORG/electron -s YOUR_COMMIT -n 'surf-PLATFORM-ARCH'`
6. Wait a very, very long time for the build to complete.
[asar]: https://github.com/electron/asar

View File

@@ -1,194 +0,0 @@
# Application Packaging
To mitigate [issues](https://github.com/joyent/node/issues/6960) around long
path names on Windows, slightly speed up `require` and conceal your source code
from cursory inspection, you can choose to package your app into an [asar][asar]
archive with little changes to your source code.
Most users will get this feature for free, since it's supported out of the box
by [`electron-packager`][electron-packager], [`electron-forge`][electron-forge],
and [`electron-builder`][electron-builder]. If you are not using any of these
tools, read on.
## Generating `asar` Archives
An [asar][asar] archive is a simple tar-like format that concatenates files
into a single file. Electron can read arbitrary files from it without unpacking
the whole file.
Steps to package your app into an `asar` archive:
### 1. Install the asar Utility
```sh
$ npm install -g asar
```
### 2. Package with `asar pack`
```sh
$ asar pack your-app app.asar
```
## Using `asar` Archives
In Electron there are two sets of APIs: Node APIs provided by Node.js and Web
APIs provided by Chromium. Both APIs support reading files from `asar` archives.
### Node API
With special patches in Electron, Node APIs like `fs.readFile` and `require`
treat `asar` archives as virtual directories, and the files in it as normal
files in the filesystem.
For example, suppose we have an `example.asar` archive under `/path/to`:
```sh
$ asar list /path/to/example.asar
/app.js
/file.txt
/dir/module.js
/static/index.html
/static/main.css
/static/jquery.min.js
```
Read a file in the `asar` archive:
```javascript
const fs = require('fs')
fs.readFileSync('/path/to/example.asar/file.txt')
```
List all files under the root of the archive:
```javascript
const fs = require('fs')
fs.readdirSync('/path/to/example.asar')
```
Use a module from the archive:
```javascript
require('./path/to/example.asar/dir/module.js')
```
You can also display a web page in an `asar` archive with `BrowserWindow`:
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.loadURL('file:///path/to/example.asar/static/index.html')
```
### Web API
In a web page, files in an archive can be requested with the `file:` protocol.
Like the Node API, `asar` archives are treated as directories.
For example, to get a file with `$.get`:
```html
<script>
let $ = require('./jquery.min.js')
$.get('file:///path/to/example.asar/file.txt', (data) => {
console.log(data)
})
</script>
```
### Treating an `asar` Archive as a Normal File
For some cases like verifying the `asar` archive's checksum, we need to read the
content of an `asar` archive as a file. For this purpose you can use the built-in
`original-fs` module which provides original `fs` APIs without `asar` support:
```javascript
const originalFs = require('original-fs')
originalFs.readFileSync('/path/to/example.asar')
```
You can also set `process.noAsar` to `true` to disable the support for `asar` in
the `fs` module:
```javascript
const fs = require('fs')
process.noAsar = true
fs.readFileSync('/path/to/example.asar')
```
## Limitations of the Node API
Even though we tried hard to make `asar` archives in the Node API work like
directories as much as possible, there are still limitations due to the
low-level nature of the Node API.
### Archives Are Read-only
The archives can not be modified so all Node APIs that can modify files will not
work with `asar` archives.
### Working Directory Can Not Be Set to Directories in Archive
Though `asar` archives are treated as directories, there are no actual
directories in the filesystem, so you can never set the working directory to
directories in `asar` archives. Passing them as the `cwd` option of some APIs
will also cause errors.
### Extra Unpacking on Some APIs
Most `fs` APIs can read a file or get a file's information from `asar` archives
without unpacking, but for some APIs that rely on passing the real file path to
underlying system calls, Electron will extract the needed file into a
temporary file and pass the path of the temporary file to the APIs to make them
work. This adds a little overhead for those APIs.
APIs that requires extra unpacking are:
* `child_process.execFile`
* `child_process.execFileSync`
* `fs.open`
* `fs.openSync`
* `process.dlopen` - Used by `require` on native modules
### Fake Stat Information of `fs.stat`
The `Stats` object returned by `fs.stat` and its friends on files in `asar`
archives is generated by guessing, because those files do not exist on the
filesystem. So you should not trust the `Stats` object except for getting file
size and checking file type.
### Executing Binaries Inside `asar` Archive
There are Node APIs that can execute binaries like `child_process.exec`,
`child_process.spawn` and `child_process.execFile`, but only `execFile` is
supported to execute binaries inside `asar` archive.
This is because `exec` and `spawn` accept `command` instead of `file` as input,
and `command`s are executed under shell. There is no reliable way to determine
whether a command uses a file in asar archive, and even if we do, we can not be
sure whether we can replace the path in command without side effects.
## Adding Unpacked Files to `asar` Archives
As stated above, some Node APIs will unpack the file to the filesystem when
called. Apart from the performance issues, various anti-virus scanners might
be triggered by this behavior.
As a workaround, you can leave various files unpacked using the `--unpack` option.
In the following example, shared libraries of native Node.js modules will not be
packed:
```sh
$ asar pack app app.asar --unpack *.node
```
After running the command, you will notice that a folder named `app.asar.unpacked`
was created together with the `app.asar` file. It contains the unpacked files
and should be shipped together with the `app.asar` archive.
[asar]: https://github.com/electron/asar
[electron-packager]: https://github.com/electron/electron-packager
[electron-forge]: https://github.com/electron-userland/electron-forge
[electron-builder]: https://github.com/electron-userland/electron-builder

View File

@@ -196,11 +196,11 @@ it may be worth your time to shop around. Popular resellers include:
There are a number of tools for signing your packaged app:
- [`electron-winstaller`] will generate an installer for windows and sign it for
* [`electron-winstaller`] will generate an installer for windows and sign it for
you
- [`electron-forge`] can sign installers it generates through the
* [`electron-forge`] can sign installers it generates through the
Squirrel.Windows or MSI targets.
- [`electron-builder`] can sign some of its windows targets
* [`electron-builder`] can sign some of its windows targets
## Windows Store

View File

@@ -19,7 +19,7 @@ the system's dark mode setting. You can do this by using the
If you want to manually switch between light/dark modes, you can do this by
setting the desired mode in the
[themeSource](https://www.electronjs.org/docs/api/native-theme#nativethemethemesource)
[themeSource](../api/native-theme.md#nativethemethemesource)
property of the `nativeTheme` module. This property's value will be propagated
to your Renderer process. Any CSS rules related to `prefers-color-scheme` will
be updated accordingly.
@@ -96,7 +96,7 @@ color scheme, and update the "Current Theme Source" label to `System`.
To add listeners and handlers, add the following lines to the `renderer.js` file:
```js
```javascript
const { ipcRenderer } = require('electron')
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
@@ -130,7 +130,7 @@ active using the `nativeTheme.shouldUseDarkColors` property, and set the
`themeSource` to the opposite theme.
* Upon receiving `dark-mode:system`, we reset the `themeSource` to `system`.
```js
```javascript
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
function createWindow () {
@@ -180,7 +180,7 @@ attribute. The value of `prefers-color-scheme` will follow your
Create a `styles.css` file and add the following lines:
```css
```css fiddle='docs/fiddles/features/macos-dark-mode'
@media (prefers-color-scheme: dark) {
body { background: #333; color: white; }
}

View File

@@ -35,7 +35,6 @@ $ code electron-quick-start
}
```
#### 3. Debugging
Set some breakpoints in `main.js`, and start debugging in the [Debug View](https://code.visualstudio.com/docs/editor/debugging). You should be able to hit the breakpoints.
@@ -84,16 +83,16 @@ $ code electron-quick-start
]
}
```
**Configuration Notes**
- `cppvsdbg` requires the [built-in C/C++ extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) be enabled.
- `${workspaceFolder}` is the full path to Chromium's `src` directory.
- `your-executable-location` will be one of the following depending on a few items:
- `Testing`: If you are using the default settings of [Electron's Build-Tools](https://github.com/electron/build-tools) or the default instructions when [building from source](https://www.electronjs.org/docs/development/build-instructions-gn#building).
- `Release`: If you built a Release build rather than a Testing build.
- `your-directory-name`: If you modified this during your build process from the default, this will be whatever you specified.
- The `args` array string `"your-electron-project-path"` should be the absolute path to either the directory or `main.js` file of the Electron project you are using for testing. In this example, it should be your path to `electron-quick-start`.
* `cppvsdbg` requires the [built-in C/C++ extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) be enabled.
* `${workspaceFolder}` is the full path to Chromium's `src` directory.
* `your-executable-location` will be one of the following depending on a few items:
* `Testing`: If you are using the default settings of [Electron's Build-Tools](https://github.com/electron/build-tools) or the default instructions when [building from source](https://www.electronjs.org/docs/development/build-instructions-gn#building).
* `Release`: If you built a Release build rather than a Testing build.
* `your-directory-name`: If you modified this during your build process from the default, this will be whatever you specified.
* The `args` array string `"your-electron-project-path"` should be the absolute path to either the directory or `main.js` file of the Electron project you are using for testing. In this example, it should be your path to `electron-quick-start`.
#### 3. Debugging

View File

@@ -20,7 +20,7 @@ Electron versions *< 2.0* did not conform to the [semver](https://semver.org) sp
Here is an example of the 1.x strategy:
![](../images/versioning-sketch-0.png)
![1.x Versioning](../images/versioning-sketch-0.png)
An app developed with `1.8.1` cannot take the `1.8.3` bug fix without either absorbing the `1.8.2` feature, or by backporting the fix and maintaining a new release line.
@@ -54,12 +54,12 @@ Note that most Chromium updates will be considered breaking. Fixes that can be b
Stabilization branches are branches that run parallel to master, taking in only cherry-picked commits that are related to security or stability. These branches are never merged back to master.
![](../images/versioning-sketch-1.png)
![Stabilization Branches](../images/versioning-sketch-1.png)
Since Electron 8, stabilization branches are always **major** version lines, and named against the following template `$MAJOR-x-y` e.g. `8-x-y`. Prior to that we used **minor** version lines and named them as `$MAJOR-$MINOR-x` e.g. `2-0-x`
We allow for multiple stabilization branches to exist simultaneously, and intend to support at least two in parallel at all times, backporting security fixes as necessary.
![](../images/versioning-sketch-2.png)
![Multiple Stability Branches](../images/versioning-sketch-2.png)
Older lines will not be supported by GitHub, but other groups can take ownership and backport stability and security fixes on their own. We discourage this, but recognize that it makes life easier for many app developers.
@@ -104,17 +104,17 @@ For each major and minor bump, you should expect to see something like the follo
An example lifecycle in pictures:
* A new release branch is created that includes the latest set of features. It is published as `2.0.0-beta.1`.
![](../images/versioning-sketch-3.png)
![New Release Branch](../images/versioning-sketch-3.png)
* A bug fix comes into master that can be backported to the release branch. The patch is applied, and a new beta is published as `2.0.0-beta.2`.
![](../images/versioning-sketch-4.png)
![Bugfix Backport to Beta](../images/versioning-sketch-4.png)
* The beta is considered _generally stable_ and it is published again as a non-beta under `2.0.0`.
![](../images/versioning-sketch-5.png)
![Beta to Stable](../images/versioning-sketch-5.png)
* Later, a zero-day exploit is revealed and a fix is applied to master. We backport the fix to the `2-0-x` line and release `2.0.1`.
![](../images/versioning-sketch-6.png)
![Security Backports](../images/versioning-sketch-6.png)
A few examples of how various semver ranges will pick up new releases:
![](../images/versioning-sketch-7.png)
![Semvers and Releases](../images/versioning-sketch-7.png)
# Missing Features: Alphas
@@ -145,7 +145,7 @@ We seek to increase clarity at all levels of the update and releases process. St
# Versioned `master`
- The `master` branch will always contain the next major version `X.0.0-nightly.DATE` in its `package.json`
- Release branches are never merged back to master
- Release branches _do_ contain the correct version in their `package.json`
- As soon as a release branch is cut for a major, master must be bumped to the next major. I.e. `master` is always versioned as the next theoretical release branch
* The `master` branch will always contain the next major version `X.0.0-nightly.DATE` in its `package.json`
* Release branches are never merged back to master
* Release branches _do_ contain the correct version in their `package.json`
* As soon as a release branch is cut for a major, master must be bumped to the next major. I.e. `master` is always versioned as the next theoretical release branch

View File

@@ -17,7 +17,7 @@ Starting with a working application from the
[Quick Start Guide](quick-start.md), update the `main.js` file with the
following lines:
```js
```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/local'
const { Menu, MenuItem } = require('electron')
const menu = new Menu()
@@ -56,7 +56,7 @@ Starting with a working application from the
[Quick Start Guide](quick-start.md), update the `main.js` file with the
following lines:
```js
```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/global'
const { app, globalShortcut } = require('electron')
app.whenReady().then(() => {
@@ -101,7 +101,7 @@ Starting with a working application from the
[Quick Start Guide](quick-start.md), update the `main.js` file with the
following lines:
```js
```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/interception-from-main'
const { app, BrowserWindow } = require('electron')
app.whenReady().then(() => {

View File

@@ -24,7 +24,7 @@ Starting with a working application from the
[Quick Start Guide](quick-start.md), update the `main.js` file with the
following lines:
```javascript
```javascript fiddle='docs/fiddles/features/macos-dock-menu'
const { app, Menu } = require('electron')
const dockMenu = Menu.buildFromTemplate([

View File

@@ -25,7 +25,7 @@ Starting with a working application from the
and add the following lines to the `renderer.js` file:
```js
```javascript
const { ipcRenderer } = require('electron')
document.getElementById('drag').ondragstart = (event) => {
@@ -40,7 +40,7 @@ and forward the information to the Main process.
In the Main process(`main.js` file), expand the received event with a path to the file that is
being dragged and an icon:
```javascript
```javascript fiddle='docs/fiddles/features/drag-and-drop'
const { ipcMain } = require('electron')
ipcMain.on('ondragstart', (event, filePath) => {

View File

@@ -28,7 +28,7 @@ Assuming you have a working Electron application from the
and add the `renderer.js` file:
```js
```javascript fiddle='docs/fiddles/features/notifications/renderer'
const myNotification = new Notification('Title', {
body: 'Notification from the Renderer process'
})
@@ -52,7 +52,7 @@ message that was generated after triggering the `onclick` event:
Starting with a working application from the
[Quick Start Guide](quick-start.md), update the `main.js` file with the following lines:
```js
```javascript fiddle='docs/fiddles/features/notifications/main'
const { Notification } = require('electron')
function showNotification () {

View File

@@ -1,59 +1,67 @@
# Offscreen Rendering
Offscreen rendering lets you obtain the content of a browser window in a bitmap,
so it can be rendered anywhere, for example on a texture in a 3D scene. The
offscreen rendering in Electron uses a similar approach than the [Chromium
Embedded Framework](https://bitbucket.org/chromiumembedded/cef) project.
## Overview
Two modes of rendering can be used and only the dirty area is passed in the
`'paint'` event to be more efficient. The rendering can be stopped, continued
and the frame rate can be set. The specified frame rate is a top limit value,
when there is nothing happening on a webpage, no frames are generated. The
maximum frame rate is 60, because above that there is no benefit, only
performance loss.
Offscreen rendering lets you obtain the content of a `BrowserWindow` in a
bitmap, so it can be rendered anywhere, for example, on texture in a 3D scene.
The offscreen rendering in Electron uses a similar approach to that of the
[Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef)
project.
**Note:** An offscreen window is always created as a [Frameless Window](../api/frameless-window.md).
*Notes*:
## Rendering Modes
* There are two rendering modes that can be used (see the section below) and only
the dirty area is passed to the `paint` event to be more efficient.
* You can stop/continue the rendering as well as set the frame rate.
* The maximum frame rate is 240 because greater values bring only performance
losses with no benefits.
* When nothing is happening on a webpage, no frames are generated.
* An offscreen window is always created as a
[Frameless Window](../api/frameless-window.md).
### GPU accelerated
### Rendering Modes
#### GPU accelerated
GPU accelerated rendering means that the GPU is used for composition. Because of
that the frame has to be copied from the GPU which requires more performance,
thus this mode is quite a bit slower than the other one. The benefit of this
that, the frame has to be copied from the GPU which requires more resources,
thus this mode is slower than the Software output device. The benefit of this
mode is that WebGL and 3D CSS animations are supported.
### Software output device
#### Software output device
This mode uses a software output device for rendering in the CPU, so the frame
generation is much faster, thus this mode is preferred over the GPU accelerated
one.
generation is much faster. As a result, this mode is preferred over the GPU
accelerated one.
To enable this mode GPU acceleration has to be disabled by calling the
To enable this mode, GPU acceleration has to be disabled by calling the
[`app.disableHardwareAcceleration()`][disablehardwareacceleration] API.
## Usage
## Example
``` javascript
Starting with a working application from the
[Quick Start Guide](quick-start.md), add the following lines to the
`main.js` file:
```javascript fiddle='docs/fiddles/features/offscreen-rendering'
const { app, BrowserWindow } = require('electron')
const fs = require('fs')
app.disableHardwareAcceleration()
let win
app.whenReady().then(() => {
win = new BrowserWindow({
webPreferences: {
offscreen: true
}
})
win = new BrowserWindow({ webPreferences: { offscreen: true } })
win.loadURL('http://github.com')
win.loadURL('https://github.com')
win.webContents.on('paint', (event, dirty, image) => {
// updateBitmap(dirty, image.getBitmap())
fs.writeFileSync('ex.png', image.toPNG())
})
win.webContents.setFrameRate(30)
win.webContents.setFrameRate(60)
})
```
After launching the Electron application, navigate to your application's
working folder.
[disablehardwareacceleration]: ../api/app.md#appdisablehardwareacceleration

View File

@@ -34,11 +34,11 @@ let onlineStatusWindow
app.whenReady().then(() => {
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false })
onlineStatusWindow.loadURL(`file://${__dirname}/online-status.html`)
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
})
```
create the `online-status.html` file and add the following line before the
in the `index.html` file, add the following line before the
closing `</body>` tag:
```html
@@ -47,7 +47,7 @@ closing `</body>` tag:
and add the `renderer.js` file:
```javascript
```javascript fiddle='docs/fiddles/features/online-detection/renderer'
const alertOnlineStatus = () => { window.alert(navigator.onLine ? 'online' : 'offline') }
window.addEventListener('online', alertOnlineStatus)
@@ -78,7 +78,7 @@ let onlineStatusWindow
app.whenReady().then(() => {
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false, webPreferences: { nodeIntegration: true } })
onlineStatusWindow.loadURL(`file://${__dirname}/online-status.html`)
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
})
ipcMain.on('online-status-changed', (event, status) => {
@@ -86,7 +86,7 @@ ipcMain.on('online-status-changed', (event, status) => {
})
```
create the `online-status.html` file and add the following line before the
in the `index.html` file, add the following line before the
closing `</body>` tag:
```html
@@ -95,7 +95,7 @@ closing `</body>` tag:
and add the `renderer.js` file:
```javascript
```javascript fiddle='docs/fiddles/features/online-detection/main'
const { ipcRenderer } = require('electron')
const updateOnlineStatus = () => { ipcRenderer.send('online-status-changed', navigator.onLine ? 'online' : 'offline') }

View File

@@ -45,7 +45,7 @@ Starting with a working application from the
[Quick Start Guide](quick-start.md), add the following lines to the
`main.js` file:
```javascript
```javascript fiddle='docs/fiddles/features/progress-bar'
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()

View File

@@ -28,7 +28,7 @@ If both commands succeeded, you are ready to install Electron.
From a development perspective, an Electron application is essentially a Node.js application. This means that the starting point of your Electron application will be a `package.json` file like in any other Node.js application. A minimal Electron application has the following structure:
```plain
```plaintext
my-electron-app/
├── package.json
├── main.js
@@ -53,7 +53,7 @@ The main script specifies the entry point of your Electron application (in our c
The main script may look as follows:
```js
```javascript fiddle='docs/fiddles/quick-start'
const { app, BrowserWindow } = require('electron')
function createWindow () {
@@ -66,7 +66,6 @@ function createWindow () {
})
win.loadFile('index.html')
win.webContents.openDevTools()
}
app.whenReady().then(createWindow)
@@ -98,7 +97,7 @@ This is the web page you want to display once the application is initialized. Th
The `index.html` page looks as follows:
```html
```html fiddle='docs/fiddles/quick-start'
<!DOCTYPE html>
<html>
<head>
@@ -108,9 +107,11 @@ The `index.html` page looks as follows:
</head>
<body style="background: white;">
<h1>Hello World!</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
<p>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</p>
</body>
</html>
```
@@ -123,6 +124,7 @@ Your Electron application uses the `package.json` file as the main entry point (
{
"name": "my-electron-app",
"version": "0.1.0",
"description": "My Electron app",
"main": "main.js"
}
```

View File

@@ -24,7 +24,7 @@ Starting with a working application from the
[Quick Start Guide](quick-start.md), add the following lines to the
`main.js` file:
```javascript
```javascript fiddle='docs/fiddles/features/recent-documents'
const { app } = require('electron')
app.addRecentDocument('/Users/USERNAME/Desktop/work.type')

View File

@@ -24,7 +24,7 @@ Starting with a working application from the
[Quick Start Guide](quick-start.md), add the following lines to the
`main.js` file:
```javascript
```javascript fiddle='docs/fiddles/features/represented-file'
const { app, BrowserWindow } = require('electron')
app.whenReady().then(() => {

View File

@@ -818,7 +818,7 @@ which potential security issues are not as widely known.
[browser-view]: ../api/browser-view.md
[webview-tag]: ../api/webview-tag.md
[web-contents]: ../api/web-contents.md
[window-open-handler]: ../api/web-contents.md#contentssetwindowopenhandler-handler
[window-open-handler]: ../api/web-contents.md#contentssetwindowopenhandlerhandler
[will-navigate]: ../api/web-contents.md#event-will-navigate
[open-external]: ../api/shell.md#shellopenexternalurl-options
[sandbox]: ../api/sandbox-option.md

View File

@@ -71,4 +71,4 @@ Although the spellchecker itself does not send any typings, words or user input
myWindow.session.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')
```
Check out the docs for [`session.setSpellCheckerDictionaryDownloadURL`](https://www.electronjs.org/docs/api/session#sessetspellcheckerdictionarydownloadurlurl) for more information on where to get the dictionary files from and how you need to host them.
Check out the docs for [`session.setSpellCheckerDictionaryDownloadURL`](../api/session.md#sessetspellcheckerdictionarydownloadurlurl) for more information on where to get the dictionary files from and how you need to host them.

View File

@@ -10,21 +10,21 @@ for answers to questions,
or to join in discussion with other developers who use Electron,
you can interact with the community in these locations:
- [`Electron's Discord`](https://discord.com/invite/electron) has channels for:
- Getting help
- Ecosystem apps like [Electron Forge](https://github.com/electron-userland/electron-forge) and [Electron Fiddle](https://github.com/electron/fiddle)
- Sharing ideas with other Electron app developers
- And more!
- [`electron`](https://discuss.atom.io/c/electron) category on the Atom forums
- `#atom-shell` channel on Freenode
- `#electron` channel on [Atom's Slack](https://discuss.atom.io/t/join-us-on-slack/16638?source_topic_id=25406)
- [`electron-ru`](https://telegram.me/electron_ru) *(Russian)*
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
- [`electron-kr`](https://electron-kr.github.io/electron-kr) *(Korean)*
- [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
- [`electron-tr`](https://electron-tr.herokuapp.com) *(Turkish)*
- [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
- [`electron-pl`](https://electronpl.github.io) *(Poland)*
* [`Electron's Discord`](https://discord.com/invite/electron) has channels for:
* Getting help
* Ecosystem apps like [Electron Forge](https://github.com/electron-userland/electron-forge) and [Electron Fiddle](https://github.com/electron/fiddle)
* Sharing ideas with other Electron app developers
* And more!
* [`electron`](https://discuss.atom.io/c/electron) category on the Atom forums
* `#atom-shell` channel on Freenode
* `#electron` channel on [Atom's Slack](https://discuss.atom.io/t/join-us-on-slack/16638?source_topic_id=25406)
* [`electron-ru`](https://telegram.me/electron_ru) *(Russian)*
* [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
* [`electron-kr`](https://electron-kr.github.io/electron-kr) *(Korean)*
* [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
* [`electron-tr`](https://electron-tr.herokuapp.com) *(Turkish)*
* [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
* [`electron-pl`](https://electronpl.github.io) *(Poland)*
If you'd like to contribute to Electron,
see the [contributing document](https://github.com/electron/electron/blob/master/CONTRIBUTING.md).
@@ -64,9 +64,9 @@ until the maintainers feel the maintenance burden is too high to continue doing
### Currently supported versions
- 11.x.y
- 10.x.y
- 9.x.y
* 11.x.y
* 10.x.y
* 9.x.y
### End-of-life

View File

@@ -1,8 +1,9 @@
# Using Native Node Modules
Native Node modules are supported by Electron, but since Electron is very
likely to use a different V8 version from the Node binary installed on your
system, the modules you use will need to be recompiled for Electron. Otherwise,
Native Node.js modules are supported by Electron, but since Electron has a different
[application binary interface (ABI)][abi] from a given Node.js binary (due to
differences such as using Chromium's BoringSSL instead of OpenSSL), the native
modules you use will need to be recompiled for Electron. Otherwise,
you will get the following class of error when you try to run your app:
```sh
@@ -23,9 +24,11 @@ You can install modules like other Node projects, and then rebuild the modules
for Electron with the [`electron-rebuild`][electron-rebuild] package. This
module can automatically determine the version of Electron and handle the
manual steps of downloading headers and rebuilding native modules for your app.
If you are using [Electron Forge][electron-forge], this tool is used automatically
in both development mode and when making distributables.
For example, to install `electron-rebuild` and then rebuild modules with it
via the command line:
For example, to install the standalone `electron-rebuild` tool and then rebuild
modules with it via the command line:
```sh
npm install --save-dev electron-rebuild
@@ -33,12 +36,12 @@ npm install --save-dev electron-rebuild
# Every time you run "npm install", run this:
./node_modules/.bin/electron-rebuild
# On Windows if you have trouble, try:
# If you have trouble on Windows, try:
.\node_modules\.bin\electron-rebuild.cmd
```
For more information on usage and integration with other tools, consult the
project's README.
For more information on usage and integration with other tools such as [Electron
Packager][electron-packager], consult the project's README.
### Using `npm`
@@ -129,13 +132,13 @@ should look like this:
In particular, it's important that:
- you link against `node.lib` from _Electron_ and not Node. If you link against
* you link against `node.lib` from _Electron_ and not Node. If you link against
the wrong `node.lib` you will get load-time errors when you require the
module in Electron.
- you include the flag `/DELAYLOAD:node.exe`. If the `node.exe` link is not
* you include the flag `/DELAYLOAD:node.exe`. If the `node.exe` link is not
delayed, then the delay-load hook won't get a chance to fire and the node
symbols won't be correctly resolved.
- `win_delay_load_hook.obj` is linked directly into the final DLL. If the hook
* `win_delay_load_hook.obj` is linked directly into the final DLL. If the hook
is set up in a dependent DLL, it won't fire at the right time.
See [`node-gyp`](https://github.com/nodejs/node-gyp/blob/e2401e1395bef1d3c8acec268b42dc5fb71c4a38/src/win_delay_load_hook.cc)
@@ -147,23 +150,25 @@ for an example delay-load hook if you're implementing your own.
native Node modules with prebuilt binaries for multiple versions of Node
and Electron.
If modules provide binaries for the usage in Electron, make sure to omit
`--build-from-source` and the `npm_config_build_from_source` environment
variable in order to take full advantage of the prebuilt binaries.
If the `prebuild`-powered module provide binaries for the usage in Electron,
make sure to omit `--build-from-source` and the `npm_config_build_from_source`
environment variable in order to take full advantage of the prebuilt binaries.
## Modules that rely on `node-pre-gyp`
The [`node-pre-gyp` tool][node-pre-gyp] provides a way to deploy native Node
modules with prebuilt binaries, and many popular modules are using it.
Usually those modules work fine under Electron, but sometimes when Electron uses
a newer version of V8 than Node and/or there are ABI changes, bad things may
happen. So in general, it is recommended to always build native modules from
source code. `electron-rebuild` handles this for you automatically.
Sometimes those modules work fine under Electron, but when there are no
Electron-specific binaries available, you'll need to build from source.
Because of this, it is recommended to use `electron-rebuild` for these modules.
If you are following the `npm` way of installing modules, then this is done
by default, if not, you have to pass `--build-from-source` to `npm`, or set the
`npm_config_build_from_source` environment variable.
If you are following the `npm` way of installing modules, you'll need to pass
`--build-from-source` to `npm`, or set the `npm_config_build_from_source`
environment variable.
[abi]: https://en.wikipedia.org/wiki/Application_binary_interface
[electron-rebuild]: https://github.com/electron/electron-rebuild
[electron-forge]: https://electronforge.io/
[electron-packager]: https://github.com/electron/electron-packager
[node-pre-gyp]: https://github.com/mapbox/node-pre-gyp

View File

@@ -20,7 +20,7 @@ and only allow the capabilities you want to support.
### WebViews
> Important Note:
[we do not recommend you to use use WebViews](https://www.electronjs.org/docs/api/webview-tag#warning),
[we do not recommend you to use use WebViews](../api/webview-tag.md#warning),
as this tag undergoes dramatic architectural changes that may affect stability
of your application. Consider switching to alternatives, like `iframe` and
Electron's `BrowserView`, or an architecture that avoids embedded content

View File

@@ -231,7 +231,6 @@ auto_filenames = {
"lib/browser/api/web-contents-view.ts",
"lib/browser/api/web-contents.ts",
"lib/browser/api/web-frame-main.ts",
"lib/browser/chrome-extension-shim.ts",
"lib/browser/default-menu.ts",
"lib/browser/desktop-capturer.ts",
"lib/browser/devtools.ts",

View File

@@ -689,7 +689,8 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
if (info.size === 0) return ['', false];
if (info.unpacked) {
const realPath = archive.copyFileOut(filePath);
return fs.readFileSync(realPath, { encoding: 'utf8' });
const str = fs.readFileSync(realPath, { encoding: 'utf8' });
return [str, str.length > 0];
}
logASARAccess(asarPath, filePath, info.offset);

View File

@@ -51,10 +51,6 @@ class CrashReporter {
return binding.getUploadedReports();
}
getCrashesDirectory () {
return app.getPath('crashDumps');
}
getUploadToServer () {
if (process.type === 'browser') {
return binding.getUploadToServer();

View File

@@ -1,20 +1,48 @@
import { EventEmitter } from 'events';
const { createScreen } = process._linkedBinding('electron_common_screen');
let _screen: Electron.Screen;
const createScreenIfNeeded = () => {
if (_screen === undefined) {
_screen = createScreen();
}
};
// We can't call createScreen until after app.on('ready'), but this module
// exposes an instance created by createScreen. In order to avoid
// side-effecting and calling createScreen upon import of this module, instead
// we export a proxy which lazily calls createScreen on first access.
export default new Proxy({}, {
get: (target, prop: keyof Electron.Screen) => {
if (_screen === undefined) {
_screen = createScreen();
get: (target, property: keyof Electron.Screen) => {
createScreenIfNeeded();
const value = _screen[property];
if (typeof value === 'function') {
return value.bind(_screen);
}
const v = _screen[prop];
if (typeof v === 'function') {
return v.bind(_screen);
}
return v;
return value;
},
set: (target, property: string, value: unknown) => {
createScreenIfNeeded();
return Reflect.set(_screen, property, value);
},
ownKeys: () => {
createScreenIfNeeded();
return Reflect.ownKeys(_screen);
},
has: (target, property: string) => {
createScreenIfNeeded();
return property in _screen;
},
getOwnPropertyDescriptor: (target, property: string) => {
createScreenIfNeeded();
return Reflect.getOwnPropertyDescriptor(_screen, property);
},
getPrototypeOf: () => {
// This is necessary as a result of weirdness with EventEmitterMixin
// and FunctionTemplate - we need to explicitly ensure it's returned
// in the prototype.
return EventEmitter.prototype;
}
});

View File

@@ -11,7 +11,7 @@ if ('getAppLevelAppearance' in systemPreferences) {
}
if ('getEffectiveAppearance' in systemPreferences) {
const nativeEAGetter = systemPreferences.getAppLevelAppearance;
const nativeEAGetter = systemPreferences.getEffectiveAppearance;
Object.defineProperty(systemPreferences, 'effectiveAppearance', {
get: () => nativeEAGetter.call(systemPreferences)
});

View File

@@ -131,10 +131,7 @@ WebContents.prototype.send = function (channel, ...args) {
throw new Error('Missing required channel argument');
}
const internal = false;
const sendToAll = false;
return this._send(internal, sendToAll, channel, args);
return this._send(false /* internal */, channel, args);
};
WebContents.prototype.postMessage = function (...args) {
@@ -149,20 +146,7 @@ WebContents.prototype._sendInternal = function (channel, ...args) {
throw new Error('Missing required channel argument');
}
const internal = true;
const sendToAll = false;
return this._send(internal, sendToAll, channel, args);
};
WebContents.prototype._sendInternalToAll = function (channel, ...args) {
if (typeof channel !== 'string') {
throw new Error('Missing required channel argument');
}
const internal = true;
const sendToAll = true;
return this._send(internal, sendToAll, channel, args);
return this._send(true /* internal */, channel, args);
};
WebContents.prototype.sendToFrame = function (frameId, channel, ...args) {
if (typeof channel !== 'string') {
@@ -171,10 +155,7 @@ WebContents.prototype.sendToFrame = function (frameId, channel, ...args) {
throw new Error('Missing required frameId argument');
}
const internal = false;
const sendToAll = false;
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
return this._sendToFrame(false /* internal */, frameId, channel, args);
};
WebContents.prototype._sendToFrameInternal = function (frameId, channel, ...args) {
if (typeof channel !== 'string') {
@@ -183,10 +164,7 @@ WebContents.prototype._sendToFrameInternal = function (frameId, channel, ...args
throw new Error('Missing required frameId argument');
}
const internal = true;
const sendToAll = false;
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
return this._sendToFrame(true /* internal */, frameId, channel, args);
};
// Following methods are mapped to webFrame.
@@ -199,7 +177,7 @@ const webFrameMethods = [
for (const method of webFrameMethods) {
WebContents.prototype[method] = function (...args: any[]): Promise<any> {
return ipcMainUtils.invokeInWebContents(this, false, IPC_MESSAGES.RENDERER_WEB_FRAME_METHOD, method, ...args);
return ipcMainUtils.invokeInWebContents(this, IPC_MESSAGES.RENDERER_WEB_FRAME_METHOD, method, ...args);
};
}
@@ -217,11 +195,11 @@ const waitTillCanExecuteJavaScript = async (webContents: Electron.WebContents) =
// WebContents has been loaded.
WebContents.prototype.executeJavaScript = async function (code, hasUserGesture) {
await waitTillCanExecuteJavaScript(this);
return ipcMainUtils.invokeInWebContents(this, false, IPC_MESSAGES.RENDERER_WEB_FRAME_METHOD, 'executeJavaScript', String(code), !!hasUserGesture);
return ipcMainUtils.invokeInWebContents(this, IPC_MESSAGES.RENDERER_WEB_FRAME_METHOD, 'executeJavaScript', String(code), !!hasUserGesture);
};
WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (worldId, code, hasUserGesture) {
await waitTillCanExecuteJavaScript(this);
return ipcMainUtils.invokeInWebContents(this, false, IPC_MESSAGES.RENDERER_WEB_FRAME_METHOD, 'executeJavaScriptInIsolatedWorld', worldId, code, !!hasUserGesture);
return ipcMainUtils.invokeInWebContents(this, IPC_MESSAGES.RENDERER_WEB_FRAME_METHOD, 'executeJavaScriptInIsolatedWorld', worldId, code, !!hasUserGesture);
};
// Translate the options of printToPDF.
@@ -483,16 +461,6 @@ const addReplyToEvent = (event: any) => {
};
};
const addReplyInternalToEvent = (event: any) => {
Object.defineProperty(event, '_replyInternal', {
configurable: false,
enumerable: false,
value: (...args: any[]) => {
event.sender._sendToFrameInternal(event.frameId, ...args);
}
});
};
const addReturnValueToEvent = (event: any) => {
Object.defineProperty(event, 'returnValue', {
set: (value) => event.sendReply(value),
@@ -537,7 +505,6 @@ WebContents.prototype._init = function () {
// Dispatch IPC messages to the ipc module.
this.on('-ipc-message' as any, function (this: Electron.WebContents, event: any, internal: boolean, channel: string, args: any[]) {
if (internal) {
addReplyInternalToEvent(event);
ipcMainInternal.emit(channel, event, ...args);
} else {
addReplyToEvent(event);
@@ -563,7 +530,6 @@ WebContents.prototype._init = function () {
this.on('-ipc-message-sync' as any, function (this: Electron.WebContents, event: any, internal: boolean, channel: string, args: any[]) {
addReturnValueToEvent(event);
if (internal) {
addReplyInternalToEvent(event);
ipcMainInternal.emit(channel, event, ...args);
} else {
addReplyToEvent(event);

View File

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

View File

@@ -276,7 +276,7 @@ const watchEmbedder = function (embedder: Electron.WebContents) {
const isWebViewTagEnabledCache = new WeakMap();
export const isWebViewTagEnabled = function (contents: Electron.WebContents) {
const isWebViewTagEnabled = function (contents: Electron.WebContents) {
if (!isWebViewTagEnabledCache.has(contents)) {
const webPreferences = contents.getLastWebPreferences() || {};
isWebViewTagEnabledCache.set(contents, !!webPreferences.webviewTag);

View File

@@ -132,9 +132,6 @@ app._setDefaultAppPaths(packagePath);
// Load the chrome devtools support.
require('@electron/internal/browser/devtools');
// Load the chrome extension support.
require('@electron/internal/browser/chrome-extension-shim');
if (BUILDFLAG(ENABLE_REMOTE_MODULE)) {
require('@electron/internal/browser/remote/server');
}

View File

@@ -14,7 +14,7 @@ export const handleSync = function <T extends IPCHandler> (channel: string, hand
let nextId = 0;
export function invokeInWebContents<T> (sender: Electron.WebContents, sendToAll: boolean, command: string, ...args: any[]) {
export function invokeInWebContents<T> (sender: Electron.WebContents, command: string, ...args: any[]) {
return new Promise<T>((resolve, reject) => {
const requestId = ++nextId;
const channel = `${command}_RESPONSE_${requestId}`;
@@ -33,10 +33,6 @@ export function invokeInWebContents<T> (sender: Electron.WebContents, sendToAll:
}
});
if (sendToAll) {
sender._sendInternalToAll(command, requestId, ...args);
} else {
sender._sendInternal(command, requestId, ...args);
}
sender._sendInternal(command, requestId, ...args);
});
}

View File

@@ -1,11 +1,11 @@
import { WebContents } from 'electron/main';
const v8Util = process._linkedBinding('electron_common_v8_util');
const getOwnerKey = (webContents: WebContents, contextId: string) => {
return `${webContents.id}-${contextId}`;
};
const electronIds = new WeakMap<Object, number>();
class ObjectsRegistry {
private nextId: number = 0
@@ -81,14 +81,14 @@ class ObjectsRegistry {
// Private: Saves the object into storage and assigns an ID for it.
saveToStorage (object: any) {
let id: number = v8Util.getHiddenValue(object, 'electronId');
let id = electronIds.get(object);
if (!id) {
id = ++this.nextId;
this.storage[id] = {
count: 0,
object: object
};
v8Util.setHiddenValue(object, 'electronId', id);
electronIds.set(object, id);
}
return id;
}
@@ -101,7 +101,7 @@ class ObjectsRegistry {
}
pointer.count -= 1;
if (pointer.count === 0) {
v8Util.deleteHiddenValue(pointer.object, 'electronId');
electronIds.delete(pointer.object);
delete this.storage[id];
}
}

View File

@@ -31,7 +31,7 @@ const finalizationRegistry = new FinalizationRegistry((fi: FinalizerInfo) => {
const ref = rendererFunctionCache.get(mapKey);
if (ref !== undefined && ref.deref() === undefined) {
rendererFunctionCache.delete(mapKey);
if (!fi.webContents.isDestroyed()) { fi.webContents.sendToFrame(fi.frameId, IPC_MESSAGES.RENDERER_RELEASE_CALLBACK, fi.id[0], fi.id[1]); }
if (!fi.webContents.isDestroyed()) { fi.webContents._sendToFrameInternal(fi.frameId, IPC_MESSAGES.RENDERER_RELEASE_CALLBACK, fi.id[0], fi.id[1]); }
}
});
@@ -56,6 +56,8 @@ function setCachedRendererFunction (id: RendererFunctionId, wc: electron.WebCont
return value;
}
const locationInfo = new WeakMap<Object, string>();
// Return the description of object's members:
const getObjectMembers = function (object: any): ObjectMember[] {
let names = Object.getOwnPropertyNames(object);
@@ -186,7 +188,7 @@ const throwRPCError = function (message: string) {
};
const removeRemoteListenersAndLogWarning = (sender: any, callIntoRenderer: (...args: any[]) => void) => {
const location = v8Util.getHiddenValue(callIntoRenderer, 'location');
const location = locationInfo.get(callIntoRenderer);
let message = 'Attempting to call a function in a renderer window that has been closed or released.' +
`\nFunction provided here: ${location}`;
@@ -269,7 +271,7 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
removeRemoteListenersAndLogWarning(this, callIntoRenderer);
}
};
v8Util.setHiddenValue(callIntoRenderer, 'location', meta.location);
locationInfo.set(callIntoRenderer, meta.location);
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length });
setCachedRendererFunction(objectId, sender, frameId, callIntoRenderer);

View File

@@ -1,10 +1,9 @@
import { app } from 'electron/main';
import type { WebContents } from 'electron/main';
import { clipboard, crashReporter, nativeImage } from 'electron/common';
import { clipboard, nativeImage } from 'electron/common';
import * as fs from 'fs';
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-utils';
import * as guestViewManager from '@electron/internal/browser/guest-view-manager';
import * as typeUtils from '@electron/internal/common/type-utils';
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
@@ -74,10 +73,6 @@ if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
});
}
const isRemoteModuleEnabled = BUILDFLAG(ENABLE_REMOTE_MODULE)
? require('@electron/internal/browser/remote/server').isRemoteModuleEnabled
: () => false;
const getPreloadScript = async function (preloadPath: string) {
let preloadSrc = null;
let preloadError = null;
@@ -91,14 +86,9 @@ const getPreloadScript = async function (preloadPath: string) {
ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_SANDBOX_LOAD, async function (event) {
const preloadPaths = event.sender._getPreloadPaths();
const webPreferences = event.sender.getLastWebPreferences() || {};
return {
preloadScripts: await Promise.all(preloadPaths.map(path => getPreloadScript(path))),
isRemoteModuleEnabled: isRemoteModuleEnabled(event.sender),
isWebViewTagEnabled: guestViewManager.isWebViewTagEnabled(event.sender),
guestInstanceId: webPreferences.guestInstanceId,
openerId: webPreferences.openerId,
process: {
arch: process.arch,
platform: process.platform,
@@ -114,26 +104,6 @@ ipcMainInternal.on(IPC_MESSAGES.BROWSER_PRELOAD_ERROR, function (event, preloadP
event.sender.emit('preload-error', event, preloadPath, error);
});
ipcMainUtils.handleSync(IPC_MESSAGES.CRASH_REPORTER_GET_LAST_CRASH_REPORT, () => {
return crashReporter.getLastCrashReport();
});
ipcMainUtils.handleSync(IPC_MESSAGES.CRASH_REPORTER_GET_UPLOADED_REPORTS, () => {
return crashReporter.getUploadedReports();
});
ipcMainUtils.handleSync(IPC_MESSAGES.CRASH_REPORTER_GET_UPLOAD_TO_SERVER, () => {
return crashReporter.getUploadToServer();
});
ipcMainUtils.handleSync(IPC_MESSAGES.CRASH_REPORTER_SET_UPLOAD_TO_SERVER, (event, uploadToServer: boolean) => {
return crashReporter.setUploadToServer(uploadToServer);
});
ipcMainUtils.handleSync(IPC_MESSAGES.CRASH_REPORTER_GET_CRASHES_DIRECTORY, () => {
return crashReporter.getCrashesDirectory();
});
ipcMainInternal.handle(IPC_MESSAGES.NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH, async (_, path: string, size: Electron.Size) => {
return typeUtils.serialize(await nativeImage.createThumbnailFromPath(path, size));
});

View File

@@ -1,7 +1,3 @@
import { deprecate } from 'electron/main';
const shell = process._linkedBinding('electron_common_shell');
shell.moveItemToTrash = deprecate.renameFunction(shell.moveItemToTrash, 'shell.trashItem');
export default shell;

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