mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
131 Commits
v12.0.9
...
v13.0.0-ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d31f1ad4c | ||
|
|
30fa427a9a | ||
|
|
1078590bbd | ||
|
|
8383c14aba | ||
|
|
729c45637d | ||
|
|
3a970825b2 | ||
|
|
bf24759354 | ||
|
|
8f1bc338e5 | ||
|
|
cdc94e4cef | ||
|
|
f99ea7c0ba | ||
|
|
a55e028b12 | ||
|
|
da3d21e5e3 | ||
|
|
8cbcb04e84 | ||
|
|
6a3679dc55 | ||
|
|
8f9058ea72 | ||
|
|
75247d18d0 | ||
|
|
9377b04e0b | ||
|
|
e250a2d804 | ||
|
|
420eaaa294 | ||
|
|
998f17ee59 | ||
|
|
9eab298779 | ||
|
|
e01b1831d9 | ||
|
|
1e2a2004e9 | ||
|
|
6932e17088 | ||
|
|
6ccebdf712 | ||
|
|
b266b5208a | ||
|
|
21024011d7 | ||
|
|
833baa4c54 | ||
|
|
ef49fea5eb | ||
|
|
9b02d94e97 | ||
|
|
b73b343e29 | ||
|
|
4588a41161 | ||
|
|
c8eb4ecc0c | ||
|
|
2f9281519c | ||
|
|
44ca6e0818 | ||
|
|
28ae68d66c | ||
|
|
b4c1e54ed3 | ||
|
|
cc09da6233 | ||
|
|
a8e9140c26 | ||
|
|
b9c9e7fc06 | ||
|
|
51db2a6b34 | ||
|
|
e641a747fb | ||
|
|
f876154fd3 | ||
|
|
cec6378881 | ||
|
|
9908cc363a | ||
|
|
bc6fed5eda | ||
|
|
07a1c2a3e5 | ||
|
|
76f721474e | ||
|
|
1a79bedb27 | ||
|
|
edfbeb92bf | ||
|
|
6d0a0319e1 | ||
|
|
19ff18ac40 | ||
|
|
c41b8d536b | ||
|
|
7677576da8 | ||
|
|
1abd36f6c8 | ||
|
|
788e51127f | ||
|
|
ee0550efca | ||
|
|
b788ceb7bd | ||
|
|
e87061398b | ||
|
|
c9b813a1f9 | ||
|
|
3bc220db29 | ||
|
|
6001f03e46 | ||
|
|
771e34a53a | ||
|
|
3db4e612f4 | ||
|
|
03b43e4d8c | ||
|
|
e89b3ca1d1 | ||
|
|
d3b1566181 | ||
|
|
5a5d964720 | ||
|
|
228a184b48 | ||
|
|
7672aa9525 | ||
|
|
b111bba387 | ||
|
|
b133b6fd45 | ||
|
|
45eee46864 | ||
|
|
5521f8acca | ||
|
|
b37982987a | ||
|
|
8eee9d1290 | ||
|
|
6fc5ff77c1 | ||
|
|
cffb51e141 | ||
|
|
e96fa95b94 | ||
|
|
efca7007b6 | ||
|
|
c2909a3b8d | ||
|
|
430189fa84 | ||
|
|
94381cda49 | ||
|
|
528b0f0e74 | ||
|
|
cdcee04bbe | ||
|
|
6c5f7a6e86 | ||
|
|
32d4c9ad85 | ||
|
|
acfbbe9869 | ||
|
|
4e3e3d414d | ||
|
|
61f339d3aa | ||
|
|
cf970f31a3 | ||
|
|
9c26be7b43 | ||
|
|
19954126e0 | ||
|
|
7d49ce898a | ||
|
|
09d7b2bc91 | ||
|
|
59b4d5c156 | ||
|
|
36af8022ca | ||
|
|
14c8e000cb | ||
|
|
c8c41fb727 | ||
|
|
fadd513739 | ||
|
|
770e245de5 | ||
|
|
7cc571801c | ||
|
|
8311ea1a36 | ||
|
|
022bafc485 | ||
|
|
d0cf16263e | ||
|
|
ba629e3127 | ||
|
|
662077f153 | ||
|
|
d56861eaa5 | ||
|
|
38ab829ea6 | ||
|
|
87e20f2b97 | ||
|
|
6761814f14 | ||
|
|
c8d77cae4a | ||
|
|
0be6c92aa9 | ||
|
|
956892dd5b | ||
|
|
a5c612cd96 | ||
|
|
9d54fdfd12 | ||
|
|
b894151745 | ||
|
|
e455a79218 | ||
|
|
b1b25607ee | ||
|
|
6932e02eb8 | ||
|
|
854d2b1574 | ||
|
|
329494cfeb | ||
|
|
abb1504ecc | ||
|
|
b57ae67da6 | ||
|
|
2e239ea563 | ||
|
|
7c099210b4 | ||
|
|
46972abf8b | ||
|
|
b4196ca486 | ||
|
|
06158b3e94 | ||
|
|
18f004eab1 | ||
|
|
03a70896c7 |
@@ -261,7 +261,7 @@ step-gclient-sync: &step-gclient-sync
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
# There are changes to the patches. Make a git commit with the updated patches
|
||||
git add patches
|
||||
GIT_COMMITTER_NAME="PatchUp" GIT_COMMITTER_EMAIL="73610968+patchup[bot]@users.noreply.github.com" git commit -m "chore: update patches" --author="PatchUp <73610968+patchup[bot]@users.noreply.github.com>"
|
||||
GIT_COMMITTER_NAME="Electron Bot" GIT_COMMITTER_EMAIL="electron@github.com" git commit -m "update patches" --author="Electron Bot <electron@github.com>"
|
||||
# Export it
|
||||
mkdir -p ../../patches
|
||||
git format-patch -1 --stdout --keep-subject --no-stat --full-index > ../../patches/update-patches.patch
|
||||
@@ -308,26 +308,23 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
npm install
|
||||
mkdir third_party
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
third_party/goma/goma_ctl.py ensure_start
|
||||
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
|
||||
echo 'export GOMA_FALLBACK_ON_AUTH_FAILURE=true' >> $BASH_ENV
|
||||
cd ..
|
||||
|
||||
step-restore-brew-cache: &step-restore-brew-cache
|
||||
restore_cache:
|
||||
paths:
|
||||
- /usr/local/Cellar/gnu-tar
|
||||
- /usr/local/bin/gtar
|
||||
- /usr/local/Homebrew
|
||||
keys:
|
||||
- v4-brew-cache-{{ arch }}
|
||||
- v2-brew-cache-{{ arch }}
|
||||
|
||||
step-save-brew-cache: &step-save-brew-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- /usr/local/Cellar/gnu-tar
|
||||
- /usr/local/bin/gtar
|
||||
key: v4-brew-cache-{{ arch }}
|
||||
- /usr/local/Homebrew
|
||||
key: v2-brew-cache-{{ arch }}
|
||||
name: Persisting brew cache
|
||||
|
||||
step-get-more-space-on-mac: &step-get-more-space-on-mac
|
||||
@@ -464,10 +461,8 @@ step-install-gnutar-on-mac: &step-install-gnutar-on-mac
|
||||
name: Install gnu-tar on macos
|
||||
command: |
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
if [ ! -d /usr/local/Cellar/gnu-tar/ ]; then
|
||||
brew update
|
||||
brew install gnu-tar
|
||||
fi
|
||||
brew update
|
||||
brew install gnu-tar
|
||||
ln -fs /usr/local/bin/gtar /usr/local/bin/tar
|
||||
fi
|
||||
|
||||
@@ -1199,6 +1194,7 @@ steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-cha
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-setup-env-for-build
|
||||
- *step-setup-goma-for-build
|
||||
- *step-restore-brew-cache
|
||||
- *step-get-more-space-on-mac
|
||||
- *step-install-npm-deps-on-mac
|
||||
- *step-fix-sync-on-mac
|
||||
@@ -1423,9 +1419,6 @@ commands:
|
||||
restore-src-cache:
|
||||
type: boolean
|
||||
default: true
|
||||
preserve-vendor-dirs:
|
||||
type: boolean
|
||||
default: false
|
||||
steps:
|
||||
- when:
|
||||
condition: << parameters.attach >>
|
||||
@@ -1463,26 +1456,11 @@ commands:
|
||||
- store_artifacts:
|
||||
path: patches
|
||||
# These next few steps reset Electron to the correct commit regardless of which cache was restored
|
||||
- when:
|
||||
condition: << parameters.preserve-vendor-dirs >>
|
||||
steps:
|
||||
- run:
|
||||
name: Preserve vendor dirs for release
|
||||
command: |
|
||||
mv src/electron/vendor/requests .
|
||||
- run:
|
||||
name: Wipe Electron
|
||||
command: rm -rf src/electron
|
||||
- *step-checkout-electron
|
||||
- *step-run-electron-only-hooks
|
||||
- when:
|
||||
condition: << parameters.preserve-vendor-dirs >>
|
||||
steps:
|
||||
- run:
|
||||
name: Preserve vendor dirs for release
|
||||
command: |
|
||||
rm -rf src/electron/vendor/requests
|
||||
mv requests src/electron/vendor/requests
|
||||
- *step-generate-deps-hash-cleanly
|
||||
- *step-mark-sync-done
|
||||
- *step-minimize-workspace-size-from-checkout
|
||||
@@ -1678,7 +1656,7 @@ jobs:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
<<: *env-linux-2xlarge
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True --custom-var=checkout_requests=True'
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
steps:
|
||||
- electron-build:
|
||||
persist: false
|
||||
@@ -1686,7 +1664,6 @@ jobs:
|
||||
checkout: true
|
||||
persist-checkout: true
|
||||
restore-src-cache: false
|
||||
preserve-vendor-dirs: true
|
||||
|
||||
linux-checkout-fast:
|
||||
<<: *machine-linux-2xlarge
|
||||
@@ -1737,7 +1714,7 @@ jobs:
|
||||
<<: *env-linux-2xlarge
|
||||
<<: *env-testing-build
|
||||
<<: *env-macos-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac --custom-var=checkout_requests=True'
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
|
||||
steps:
|
||||
- electron-build:
|
||||
persist: false
|
||||
@@ -1745,7 +1722,6 @@ jobs:
|
||||
checkout: true
|
||||
persist-checkout: true
|
||||
restore-src-cache: false
|
||||
preserve-vendor-dirs: true
|
||||
|
||||
mac-checkout-fast:
|
||||
<<: *machine-linux-2xlarge
|
||||
@@ -1822,7 +1798,6 @@ jobs:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
<<: *env-linux-2xlarge-release
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_requests=True'
|
||||
<<: *env-release-build
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
@@ -1875,7 +1850,6 @@ jobs:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
<<: *env-linux-2xlarge-release
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_requests=True'
|
||||
<<: *env-ia32
|
||||
<<: *env-release-build
|
||||
<<: *env-32bit-release
|
||||
@@ -1936,7 +1910,7 @@ jobs:
|
||||
<<: *env-arm
|
||||
<<: *env-release-build
|
||||
<<: *env-32bit-release
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_requests=True'
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True'
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
@@ -2001,7 +1975,7 @@ jobs:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-arm64
|
||||
<<: *env-release-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm64=True --custom-var=checkout_requests=True'
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm64=True'
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
@@ -2063,7 +2037,6 @@ jobs:
|
||||
environment:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-release-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_requests=True'
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
@@ -2077,7 +2050,6 @@ jobs:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-release-build
|
||||
<<: *env-apple-silicon
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_requests=True'
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
@@ -2171,7 +2143,6 @@ jobs:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-mas
|
||||
<<: *env-release-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_requests=True'
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
@@ -2185,7 +2156,6 @@ jobs:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-mas-apple-silicon
|
||||
<<: *env-release-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_requests=True'
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
@@ -2537,19 +2507,15 @@ workflows:
|
||||
- osx-publish-x64-skip-checkout:
|
||||
requires:
|
||||
- mac-checkout
|
||||
context: release-env
|
||||
- mas-publish-x64-skip-checkout:
|
||||
requires:
|
||||
- mac-checkout
|
||||
context: release-env
|
||||
- osx-publish-arm64-skip-checkout:
|
||||
requires:
|
||||
- mac-checkout
|
||||
context: release-env
|
||||
- mas-publish-arm64-skip-checkout:
|
||||
requires:
|
||||
- mac-checkout
|
||||
context: release-env
|
||||
|
||||
lint:
|
||||
when: << pipeline.parameters.run-lint >>
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
*
|
||||
!tools/xvfb-init.sh
|
||||
!build/install-build-deps.sh
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
APPVEYOR_CLOUD_TOKEN=
|
||||
CIRCLE_TOKEN=
|
||||
ELECTRON_GITHUB_TOKEN=
|
||||
VSTS_TOKEN=
|
||||
1
.github/config.yml
vendored
1
.github/config.yml
vendored
@@ -36,5 +36,6 @@ authorizedUsers:
|
||||
- loc
|
||||
- MarshallOfSound
|
||||
- miniak
|
||||
- mlaurencin
|
||||
- nornagon
|
||||
- zcbenz
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -55,7 +55,7 @@ electron.d.ts
|
||||
spec/.hash
|
||||
|
||||
# Eslint Cache
|
||||
.eslintcache
|
||||
.eslintcache*
|
||||
|
||||
# Generated native addon files
|
||||
/spec-main/fixtures/native-addon/echo/build/
|
||||
@@ -68,6 +68,4 @@ ts-gen
|
||||
.depshash-target
|
||||
|
||||
# Used to accelerate builds after sync
|
||||
patches/mtime-cache.json
|
||||
|
||||
spec/fixtures/logo.png
|
||||
patches/mtime-cache.json
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,6 +0,0 @@
|
||||
[submodule "vendor/requests"]
|
||||
path = vendor/requests
|
||||
url = https://github.com/kennethreitz/requests
|
||||
[submodule "vendor/boto"]
|
||||
path = vendor/boto
|
||||
url = https://github.com/boto/boto.git
|
||||
17
BUILD.gn
17
BUILD.gn
@@ -648,7 +648,6 @@ source_set("electron_lib") {
|
||||
}
|
||||
if (enable_pdf_viewer) {
|
||||
deps += [
|
||||
"//chrome/browser/resources/pdf:pdf_resources",
|
||||
"//components/pdf/browser",
|
||||
"//components/pdf/renderer",
|
||||
"//pdf:pdf_ppapi",
|
||||
@@ -992,9 +991,6 @@ if (is_mac) {
|
||||
deps = [
|
||||
":electron_app_framework_bundle_data",
|
||||
":electron_app_resources",
|
||||
":electron_fuses",
|
||||
"//base",
|
||||
"//electron/buildflags",
|
||||
]
|
||||
if (is_mas_build) {
|
||||
deps += [ ":electron_login_helper_app" ]
|
||||
@@ -1158,19 +1154,6 @@ if (is_mac) {
|
||||
ldflags += [ "/guard:cf,nolongjmp" ]
|
||||
}
|
||||
|
||||
if (current_cpu == "x86") {
|
||||
# Set the initial stack size to 0.5MiB, instead of the 1.5MiB needed by
|
||||
# Chrome's main thread. This saves significant memory on threads (like
|
||||
# those in the Windows thread pool, and others) whose stack size we can
|
||||
# only control through this setting. Because Chrome's main thread needs
|
||||
# a minimum 1.5 MiB stack, the main thread (in 32-bit builds only) uses
|
||||
# fibers to switch to a 1.5 MiB stack before running any other code.
|
||||
ldflags += [ "/STACK:0x80000" ]
|
||||
} else {
|
||||
# Increase the initial stack size. The default is 1MB, this is 8MB.
|
||||
ldflags += [ "/STACK:0x800000" ]
|
||||
}
|
||||
|
||||
# This is to support renaming of electron.exe. node-gyp has hard-coded
|
||||
# executable names which it will recognise as node. This module definition
|
||||
# file claims that the electron executable is in fact named "node.exe",
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
38
DEPS
38
DEPS
@@ -14,21 +14,19 @@ gclient_gn_args = [
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'89.0.4389.128',
|
||||
'b13e791d7244a08d9d61dbfa2bb2b6cdf1ff6294',
|
||||
'node_version':
|
||||
'v14.16.0',
|
||||
'v14.15.2',
|
||||
'nan_version':
|
||||
'2c4ee8a32a299eada3cd6e468bbd0a473bfea96d',
|
||||
'squirrel.mac_version':
|
||||
'cdc0729c8bf8576bfef18629186e1e9ecf1b0d9f',
|
||||
|
||||
'pyyaml_version': '3.12',
|
||||
'requests_version': 'e4d59bedfd3c7f4f254f4f5d036587bcd8152458',
|
||||
|
||||
'chromium_git': 'https://chromium.googlesource.com',
|
||||
'electron_git': 'https://github.com/electron',
|
||||
'nodejs_git': 'https://github.com/nodejs',
|
||||
'requests_git': 'https://github.com/kennethreitz',
|
||||
'yaml_git': 'https://github.com/yaml',
|
||||
'squirrel_git': 'https://github.com/Squirrel',
|
||||
|
||||
@@ -50,18 +48,11 @@ vars = {
|
||||
# It's only needed to parse the native tests configurations.
|
||||
'checkout_pyyaml': False,
|
||||
|
||||
# Python "requests" module is used for releases only.
|
||||
'checkout_requests': False,
|
||||
|
||||
'mac_xcode_version': 'default',
|
||||
|
||||
# To allow running hooks without parsing the DEPS tree
|
||||
'process_deps': True,
|
||||
|
||||
# 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':
|
||||
@@ -99,10 +90,6 @@ deps = {
|
||||
'url': (Var("yaml_git")) + '/pyyaml.git@' + (Var("pyyaml_version")),
|
||||
'condition': 'checkout_pyyaml and process_deps',
|
||||
},
|
||||
'src/electron/vendor/requests': {
|
||||
'url': Var('requests_git') + '/requests.git' + '@' + Var('requests_version'),
|
||||
'condition': 'checkout_requests and process_deps',
|
||||
},
|
||||
'src/third_party/squirrel.mac': {
|
||||
'url': Var("squirrel_git") + '/Squirrel.Mac.git@' + Var("squirrel.mac_version"),
|
||||
'condition': 'process_deps',
|
||||
@@ -157,32 +144,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"]);',
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': 'setup_requests',
|
||||
'pattern': 'src/electron',
|
||||
'condition': 'checkout_requests and process_deps',
|
||||
'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")); subprocess.check_call(["python3", "script/lib/npx.py", "yarn@' + (Var("yarn_version")) + '", "install", "--frozen-lockfile"]);',
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
@@ -1 +1 @@
|
||||
12.0.9
|
||||
13.0.0-nightly.20210104
|
||||
12
README.md
12
README.md
@@ -1,12 +1,11 @@
|
||||
[](https://electronjs.org)
|
||||
|
||||
|
||||
[](https://circleci.com/gh/electron/electron/tree/master)
|
||||
[](https://ci.appveyor.com/project/electron-bot/electron-ljo26/branch/master)
|
||||
[](https://david-dm.org/electron/electron?type=dev)
|
||||
[](https://discord.com/invite/electron)
|
||||
|
||||
:memo: Available Translations: 🇨🇳 🇧🇷 🇪🇸 🇯🇵 🇷🇺 🇫🇷 🇺🇸 🇩🇪.
|
||||
:memo: Available Translations: 🇨🇳 🇹🇼 🇧🇷 🇪🇸 🇰🇷 🇯🇵 🇷🇺 🇫🇷 🇹🇭 🇳🇱 🇹🇷 🇮🇩 🇺🇦 🇨🇿 🇮🇹 🇵🇱.
|
||||
View these docs in other languages at [electron/i18n](https://github.com/electron/i18n/tree/master/content/).
|
||||
|
||||
The Electron framework lets you write cross-platform desktop applications
|
||||
@@ -29,13 +28,16 @@ The preferred method is to install Electron as a development dependency in your
|
||||
app:
|
||||
|
||||
```sh
|
||||
npm install electron --save-dev
|
||||
npm install electron --save-dev [--save-exact]
|
||||
```
|
||||
|
||||
For more installation options and troubleshooting tips, see
|
||||
[installation](docs/tutorial/installation.md). For info on how to manage Electron versions in your apps, see
|
||||
The `--save-exact` flag is recommended for Electron prior to version 2, as it does not follow semantic
|
||||
versioning. As of version 2.0.0, Electron follows semver, so you don't need `--save-exact` flag. For info on how to manage Electron versions in your apps, see
|
||||
[Electron versioning](docs/tutorial/electron-versioning.md).
|
||||
|
||||
For more installation options and troubleshooting tips, see
|
||||
[installation](docs/tutorial/installation.md).
|
||||
|
||||
## Quick start & Electron Fiddle
|
||||
|
||||
Use [`Electron Fiddle`](https://github.com/electron/fiddle)
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -36,7 +36,6 @@ environment:
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
notifications:
|
||||
- provider: Webhook
|
||||
url: https://electron-mission-control.herokuapp.com/rest/appveyor-hook
|
||||
@@ -68,9 +67,7 @@ build_script:
|
||||
- ps: Move-Item $env:APPVEYOR_BUILD_FOLDER -Destination src\electron
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
$env:GCLIENT_EXTRA_ARGS="$env:GCLIENT_EXTRA_ARGS --custom-var=checkout_requests=True"
|
||||
} else {
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
$env:NINJA_STATUS="[%r processes, %f/%t @ %o/s : %es] "
|
||||
}
|
||||
- >-
|
||||
@@ -99,8 +96,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
|
||||
|
||||
@@ -93,6 +93,6 @@ steps:
|
||||
condition: always()
|
||||
|
||||
- powershell: |
|
||||
Remove-Item -path $env:APPDATA/Electron* -Recurse -Force -ErrorAction Ignore
|
||||
Remove-Item -path $env:APPDATA/Electron* -Recurse
|
||||
displayName: 'Delete user app data directories'
|
||||
condition: always()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,653 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
# Script to install everything needed to build chromium (well, ideally, anyway)
|
||||
# See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_build_instructions.md
|
||||
usage() {
|
||||
echo "Usage: $0 [--options]"
|
||||
echo "Options:"
|
||||
echo "--[no-]syms: enable or disable installation of debugging symbols"
|
||||
echo "--lib32: enable installation of 32-bit libraries, e.g. for V8 snapshot"
|
||||
echo "--[no-]arm: enable or disable installation of arm cross toolchain"
|
||||
echo "--[no-]chromeos-fonts: enable or disable installation of Chrome OS"\
|
||||
"fonts"
|
||||
echo "--[no-]nacl: enable or disable installation of prerequisites for"\
|
||||
"building standalone NaCl and all its toolchains"
|
||||
echo "--[no-]backwards-compatible: enable or disable installation of packages
|
||||
that are no longer currently needed and have been removed from this
|
||||
script. Useful for bisection."
|
||||
echo "--no-prompt: silently select standard options/defaults"
|
||||
echo "--quick-check: quickly try to determine if dependencies are installed"
|
||||
echo " (this avoids interactive prompts and sudo commands,"
|
||||
echo " so might not be 100% accurate)"
|
||||
echo "--unsupported: attempt installation even on unsupported systems"
|
||||
echo "Script will prompt interactively if options not given."
|
||||
exit 1
|
||||
}
|
||||
# Checks whether a particular package is available in the repos.
|
||||
# USAGE: $ package_exists <package name>
|
||||
package_exists() {
|
||||
# 'apt-cache search' takes a regex string, so eg. the +'s in packages like
|
||||
# "libstdc++" need to be escaped.
|
||||
local escaped="$(echo $1 | sed 's/[\~\+\.\:-]/\\&/g')"
|
||||
[ ! -z "$(apt-cache search --names-only "${escaped}" | \
|
||||
awk '$1 == "'$1'" { print $1; }')" ]
|
||||
}
|
||||
# These default to on because (some) bots need them and it keeps things
|
||||
# simple for the bot setup if all bots just run the script in its default
|
||||
# mode. Developers who don't want stuff they don't need installed on their
|
||||
# own workstations can pass --no-arm --no-nacl when running the script.
|
||||
do_inst_arm=1
|
||||
do_inst_nacl=1
|
||||
while [ "$1" != "" ]
|
||||
do
|
||||
case "$1" in
|
||||
--syms) do_inst_syms=1;;
|
||||
--no-syms) do_inst_syms=0;;
|
||||
--lib32) do_inst_lib32=1;;
|
||||
--arm) do_inst_arm=1;;
|
||||
--no-arm) do_inst_arm=0;;
|
||||
--chromeos-fonts) do_inst_chromeos_fonts=1;;
|
||||
--no-chromeos-fonts) do_inst_chromeos_fonts=0;;
|
||||
--nacl) do_inst_nacl=1;;
|
||||
--no-nacl) do_inst_nacl=0;;
|
||||
--backwards-compatible) do_inst_backwards_compatible=1;;
|
||||
--no-backwards-compatible) do_inst_backwards_compatible=0;;
|
||||
--add-cross-tool-repo) add_cross_tool_repo=1;;
|
||||
--no-prompt) do_default=1
|
||||
do_quietly="-qq --assume-yes"
|
||||
;;
|
||||
--quick-check) do_quick_check=1;;
|
||||
--unsupported) do_unsupported=1;;
|
||||
*) usage;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
if [ "$do_inst_arm" = "1" ]; then
|
||||
do_inst_lib32=1
|
||||
fi
|
||||
# Check for lsb_release command in $PATH
|
||||
if ! which lsb_release > /dev/null; then
|
||||
echo "ERROR: lsb_release not found in \$PATH" >&2
|
||||
exit 1;
|
||||
fi
|
||||
distro_codename=$(lsb_release --codename --short)
|
||||
distro_id=$(lsb_release --id --short)
|
||||
supported_codenames="(trusty|xenial|artful|bionic)"
|
||||
supported_ids="(Debian)"
|
||||
if [ 0 -eq "${do_unsupported-0}" ] && [ 0 -eq "${do_quick_check-0}" ] ; then
|
||||
if [[ ! $distro_codename =~ $supported_codenames &&
|
||||
! $distro_id =~ $supported_ids ]]; then
|
||||
echo -e "ERROR: The only supported distros are\n" \
|
||||
"\tUbuntu 14.04 LTS (trusty)\n" \
|
||||
"\tUbuntu 16.04 LTS (xenial)\n" \
|
||||
"\tUbuntu 17.10 (artful)\n" \
|
||||
"\tUbuntu 18.04 LTS (bionic)\n" \
|
||||
"\tDebian 8 (jessie) or later" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! uname -m | egrep -q "i686|x86_64"; then
|
||||
echo "Only x86 architectures are currently supported" >&2
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
if [ "x$(id -u)" != x0 ] && [ 0 -eq "${do_quick_check-0}" ]; then
|
||||
echo "Running as non-root user."
|
||||
echo "You might have to enter your password one or more times for 'sudo'."
|
||||
echo
|
||||
fi
|
||||
# Packages needed for chromeos only
|
||||
chromeos_dev_list="libbluetooth-dev libxkbcommon-dev"
|
||||
if package_exists realpath; then
|
||||
chromeos_dev_list="${chromeos_dev_list} realpath"
|
||||
fi
|
||||
# Packages needed for development
|
||||
dev_list="\
|
||||
binutils
|
||||
bison
|
||||
bzip2
|
||||
cdbs
|
||||
curl
|
||||
dbus-x11
|
||||
dpkg-dev
|
||||
elfutils
|
||||
devscripts
|
||||
fakeroot
|
||||
flex
|
||||
g++
|
||||
git-core
|
||||
git-svn
|
||||
gperf
|
||||
libappindicator3-dev
|
||||
libasound2-dev
|
||||
libatspi2.0-dev
|
||||
libbrlapi-dev
|
||||
libbz2-dev
|
||||
libcairo2-dev
|
||||
libcap-dev
|
||||
libcups2-dev
|
||||
libcurl4-gnutls-dev
|
||||
libdrm-dev
|
||||
libelf-dev
|
||||
libffi-dev
|
||||
libgbm-dev
|
||||
libglib2.0-dev
|
||||
libglu1-mesa-dev
|
||||
libgnome-keyring-dev
|
||||
libgtk-3-dev
|
||||
libkrb5-dev
|
||||
libnspr4-dev
|
||||
libnss3-dev
|
||||
libpam0g-dev
|
||||
libpci-dev
|
||||
libpulse-dev
|
||||
libsctp-dev
|
||||
libspeechd-dev
|
||||
libsqlite3-dev
|
||||
libssl-dev
|
||||
libudev-dev
|
||||
libwww-perl
|
||||
libxslt1-dev
|
||||
libxss-dev
|
||||
libxt-dev
|
||||
libxtst-dev
|
||||
locales
|
||||
openbox
|
||||
p7zip
|
||||
patch
|
||||
perl
|
||||
pkg-config
|
||||
python
|
||||
python-cherrypy3
|
||||
python-crypto
|
||||
python-dev
|
||||
python-numpy
|
||||
python-opencv
|
||||
python-openssl
|
||||
python-psutil
|
||||
python-yaml
|
||||
rpm
|
||||
ruby
|
||||
subversion
|
||||
uuid-dev
|
||||
wdiff
|
||||
x11-utils
|
||||
xcompmgr
|
||||
xz-utils
|
||||
zip
|
||||
$chromeos_dev_list
|
||||
"
|
||||
# 64-bit systems need a minimum set of 32-bit compat packages for the pre-built
|
||||
# NaCl binaries.
|
||||
if file -L /sbin/init | grep -q 'ELF 64-bit'; then
|
||||
dev_list="${dev_list} libc6-i386 lib32gcc1 lib32stdc++6"
|
||||
fi
|
||||
# Run-time libraries required by chromeos only
|
||||
chromeos_lib_list="libpulse0 libbz2-1.0"
|
||||
# List of required run-time libraries
|
||||
common_lib_list="\
|
||||
libappindicator3-1
|
||||
libasound2
|
||||
libatk1.0-0
|
||||
libatspi2.0-0
|
||||
libc6
|
||||
libcairo2
|
||||
libcap2
|
||||
libcups2
|
||||
libexpat1
|
||||
libffi6
|
||||
libfontconfig1
|
||||
libfreetype6
|
||||
libglib2.0-0
|
||||
libgnome-keyring0
|
||||
libgtk-3-0
|
||||
libpam0g
|
||||
libpango1.0-0
|
||||
libpci3
|
||||
libpcre3
|
||||
libpixman-1-0
|
||||
libspeechd2
|
||||
libstdc++6
|
||||
libsqlite3-0
|
||||
libuuid1
|
||||
libwayland-egl1-mesa
|
||||
libx11-6
|
||||
libx11-xcb1
|
||||
libxau6
|
||||
libxcb1
|
||||
libxcomposite1
|
||||
libxcursor1
|
||||
libxdamage1
|
||||
libxdmcp6
|
||||
libxext6
|
||||
libxfixes3
|
||||
libxi6
|
||||
libxinerama1
|
||||
libxrandr2
|
||||
libxrender1
|
||||
libxtst6
|
||||
zlib1g
|
||||
"
|
||||
# Full list of required run-time libraries
|
||||
lib_list="\
|
||||
$common_lib_list
|
||||
$chromeos_lib_list
|
||||
"
|
||||
# 32-bit libraries needed e.g. to compile V8 snapshot for Android or armhf
|
||||
lib32_list="linux-libc-dev:i386 libpci3:i386"
|
||||
# 32-bit libraries needed for a 32-bit build
|
||||
lib32_list="$lib32_list libx11-xcb1:i386"
|
||||
# Packages that have been removed from this script. Regardless of configuration
|
||||
# or options passed to this script, whenever a package is removed, it should be
|
||||
# added here.
|
||||
backwards_compatible_list="\
|
||||
7za
|
||||
fonts-indic
|
||||
fonts-ipafont
|
||||
fonts-stix
|
||||
fonts-thai-tlwg
|
||||
fonts-tlwg-garuda
|
||||
language-pack-da
|
||||
language-pack-fr
|
||||
language-pack-he
|
||||
language-pack-zh-hant
|
||||
libappindicator-dev
|
||||
libappindicator1
|
||||
libappindicator3-1:i386
|
||||
libexif-dev
|
||||
libexif12
|
||||
libexif12:i386
|
||||
libgbm-dev
|
||||
libgl1-mesa-dev
|
||||
libgl1-mesa-glx:i386
|
||||
libgles2-mesa-dev
|
||||
libgtk2.0-0
|
||||
libgtk2.0-0:i386
|
||||
libgtk2.0-dev
|
||||
mesa-common-dev
|
||||
msttcorefonts
|
||||
ttf-dejavu-core
|
||||
ttf-indic-fonts
|
||||
ttf-kochi-gothic
|
||||
ttf-kochi-mincho
|
||||
ttf-mscorefonts-installer
|
||||
xfonts-mathml
|
||||
"
|
||||
case $distro_codename in
|
||||
trusty)
|
||||
backwards_compatible_list+=" \
|
||||
libgbm-dev-lts-trusty
|
||||
libgl1-mesa-dev-lts-trusty
|
||||
libgl1-mesa-glx-lts-trusty:i386
|
||||
libgles2-mesa-dev-lts-trusty
|
||||
mesa-common-dev-lts-trusty"
|
||||
;;
|
||||
xenial)
|
||||
backwards_compatible_list+=" \
|
||||
libgbm-dev-lts-xenial
|
||||
libgl1-mesa-dev-lts-xenial
|
||||
libgl1-mesa-glx-lts-xenial:i386
|
||||
libgles2-mesa-dev-lts-xenial
|
||||
mesa-common-dev-lts-xenial"
|
||||
;;
|
||||
esac
|
||||
# arm cross toolchain packages needed to build chrome on armhf
|
||||
EM_REPO="deb http://emdebian.org/tools/debian/ jessie main"
|
||||
EM_SOURCE=$(cat <<EOF
|
||||
# Repo added by Chromium $0
|
||||
${EM_REPO}
|
||||
# deb-src http://emdebian.org/tools/debian/ jessie main
|
||||
EOF
|
||||
)
|
||||
EM_ARCHIVE_KEY_FINGER="084C6C6F39159EDB67969AA87DE089671804772E"
|
||||
GPP_ARM_PACKAGE="g++-arm-linux-gnueabihf"
|
||||
case $distro_codename in
|
||||
jessie)
|
||||
eval $(apt-config shell APT_SOURCESDIR 'Dir::Etc::sourceparts/d')
|
||||
CROSSTOOLS_LIST="${APT_SOURCESDIR}/crosstools.list"
|
||||
arm_list="libc6-dev:armhf
|
||||
linux-libc-dev:armhf"
|
||||
if [ "$do_inst_arm" = "1" ]; then
|
||||
if $(dpkg-query -W ${GPP_ARM_PACKAGE} &>/dev/null); then
|
||||
arm_list+=" ${GPP_ARM_PACKAGE}"
|
||||
else
|
||||
if [ "${add_cross_tool_repo}" = "1" ]; then
|
||||
gpg --keyserver pgp.mit.edu --recv-keys ${EM_ARCHIVE_KEY_FINGER}
|
||||
gpg -a --export ${EM_ARCHIVE_KEY_FINGER} | sudo apt-key add -
|
||||
if ! grep "^${EM_REPO}" "${CROSSTOOLS_LIST}" &>/dev/null; then
|
||||
echo "${EM_SOURCE}" | sudo tee -a "${CROSSTOOLS_LIST}" >/dev/null
|
||||
fi
|
||||
arm_list+=" ${GPP_ARM_PACKAGE}"
|
||||
else
|
||||
echo "The Debian Cross-toolchains repository is necessary to"
|
||||
echo "cross-compile Chromium for arm."
|
||||
echo "Rerun with --add-deb-cross-tool-repo to have it added for you."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
# All necessary ARM packages are available on the default repos on
|
||||
# Debian 9 and later.
|
||||
*)
|
||||
arm_list="libc6-dev-armhf-cross
|
||||
linux-libc-dev-armhf-cross
|
||||
${GPP_ARM_PACKAGE}"
|
||||
;;
|
||||
esac
|
||||
# Work around for dependency issue Ubuntu/Trusty: http://crbug.com/435056
|
||||
case $distro_codename in
|
||||
trusty)
|
||||
arm_list+=" g++-4.8-multilib-arm-linux-gnueabihf
|
||||
gcc-4.8-multilib-arm-linux-gnueabihf"
|
||||
;;
|
||||
xenial|artful|bionic)
|
||||
arm_list+=" g++-5-multilib-arm-linux-gnueabihf
|
||||
gcc-5-multilib-arm-linux-gnueabihf
|
||||
gcc-arm-linux-gnueabihf"
|
||||
;;
|
||||
esac
|
||||
# Packages to build NaCl, its toolchains, and its ports.
|
||||
naclports_list="ant autoconf bison cmake gawk intltool xutils-dev xsltproc"
|
||||
nacl_list="\
|
||||
g++-mingw-w64-i686
|
||||
lib32z1-dev
|
||||
libasound2:i386
|
||||
libcap2:i386
|
||||
libelf-dev:i386
|
||||
libfontconfig1:i386
|
||||
libglib2.0-0:i386
|
||||
libgpm2:i386
|
||||
libgtk-3-0:i386
|
||||
libncurses5:i386
|
||||
lib32ncurses5-dev
|
||||
libnss3:i386
|
||||
libpango1.0-0:i386
|
||||
libssl-dev:i386
|
||||
libtinfo-dev
|
||||
libtinfo-dev:i386
|
||||
libtool
|
||||
libuuid1:i386
|
||||
libxcomposite1:i386
|
||||
libxcursor1:i386
|
||||
libxdamage1:i386
|
||||
libxi6:i386
|
||||
libxrandr2:i386
|
||||
libxss1:i386
|
||||
libxtst6:i386
|
||||
texinfo
|
||||
xvfb
|
||||
${naclports_list}
|
||||
"
|
||||
if package_exists libssl1.1; then
|
||||
nacl_list="${nacl_list} libssl1.1:i386"
|
||||
elif package_exists libssl1.0.2; then
|
||||
nacl_list="${nacl_list} libssl1.0.2:i386"
|
||||
else
|
||||
nacl_list="${nacl_list} libssl1.0.0:i386"
|
||||
fi
|
||||
# Some package names have changed over time
|
||||
if package_exists libpng16-16; then
|
||||
lib_list="${lib_list} libpng16-16"
|
||||
else
|
||||
lib_list="${lib_list} libpng12-0"
|
||||
fi
|
||||
if package_exists libnspr4; then
|
||||
lib_list="${lib_list} libnspr4 libnss3"
|
||||
else
|
||||
lib_list="${lib_list} libnspr4-0d libnss3-1d"
|
||||
fi
|
||||
if package_exists libjpeg-dev; then
|
||||
dev_list="${dev_list} libjpeg-dev"
|
||||
else
|
||||
dev_list="${dev_list} libjpeg62-dev"
|
||||
fi
|
||||
if package_exists libudev1; then
|
||||
dev_list="${dev_list} libudev1"
|
||||
nacl_list="${nacl_list} libudev1:i386"
|
||||
else
|
||||
dev_list="${dev_list} libudev0"
|
||||
nacl_list="${nacl_list} libudev0:i386"
|
||||
fi
|
||||
if package_exists libbrlapi0.6; then
|
||||
dev_list="${dev_list} libbrlapi0.6"
|
||||
else
|
||||
dev_list="${dev_list} libbrlapi0.5"
|
||||
fi
|
||||
if package_exists apache2.2-bin; then
|
||||
dev_list="${dev_list} apache2.2-bin"
|
||||
else
|
||||
dev_list="${dev_list} apache2-bin"
|
||||
fi
|
||||
if package_exists libav-tools; then
|
||||
dev_list="${dev_list} libav-tools"
|
||||
fi
|
||||
if package_exists php7.2-cgi; then
|
||||
dev_list="${dev_list} php7.2-cgi libapache2-mod-php7.2"
|
||||
elif package_exists php7.1-cgi; then
|
||||
dev_list="${dev_list} php7.1-cgi libapache2-mod-php7.1"
|
||||
elif package_exists php7.0-cgi; then
|
||||
dev_list="${dev_list} php7.0-cgi libapache2-mod-php7.0"
|
||||
else
|
||||
dev_list="${dev_list} php5-cgi libapache2-mod-php5"
|
||||
fi
|
||||
# Some packages are only needed if the distribution actually supports
|
||||
# installing them.
|
||||
if package_exists appmenu-gtk; then
|
||||
lib_list="$lib_list appmenu-gtk"
|
||||
fi
|
||||
# Cross-toolchain strip is needed for building the sysroots.
|
||||
if package_exists binutils-arm-linux-gnueabihf; then
|
||||
dev_list="${dev_list} binutils-arm-linux-gnueabihf"
|
||||
fi
|
||||
if package_exists binutils-aarch64-linux-gnu; then
|
||||
dev_list="${dev_list} binutils-aarch64-linux-gnu"
|
||||
fi
|
||||
if package_exists binutils-mipsel-linux-gnu; then
|
||||
dev_list="${dev_list} binutils-mipsel-linux-gnu"
|
||||
fi
|
||||
if package_exists binutils-mips64el-linux-gnuabi64; then
|
||||
dev_list="${dev_list} binutils-mips64el-linux-gnuabi64"
|
||||
fi
|
||||
# When cross building for arm/Android on 64-bit systems the host binaries
|
||||
# that are part of v8 need to be compiled with -m32 which means
|
||||
# that basic multilib support is needed.
|
||||
if file -L /sbin/init | grep -q 'ELF 64-bit'; then
|
||||
# gcc-multilib conflicts with the arm cross compiler (at least in trusty) but
|
||||
# g++-X.Y-multilib gives us the 32-bit support that we need. Find out the
|
||||
# appropriate value of X and Y by seeing what version the current
|
||||
# distribution's g++-multilib package depends on.
|
||||
multilib_package=$(apt-cache depends g++-multilib --important | \
|
||||
grep -E --color=never --only-matching '\bg\+\+-[0-9.]+-multilib\b')
|
||||
lib32_list="$lib32_list $multilib_package"
|
||||
fi
|
||||
if [ "$do_inst_syms" = "1" ]; then
|
||||
echo "Including debugging symbols."
|
||||
# Debian is in the process of transitioning to automatic debug packages, which
|
||||
# have the -dbgsym suffix (https://wiki.debian.org/AutomaticDebugPackages).
|
||||
# Untransitioned packages have the -dbg suffix. And on some systems, neither
|
||||
# will be available, so exclude the ones that are missing.
|
||||
dbg_package_name() {
|
||||
if package_exists "$1-dbgsym"; then
|
||||
echo "$1-dbgsym"
|
||||
elif package_exists "$1-dbg"; then
|
||||
echo "$1-dbg"
|
||||
fi
|
||||
}
|
||||
for package in "${common_lib_list}"; do
|
||||
dbg_list="$dbg_list $(dbg_package_name ${package})"
|
||||
done
|
||||
# Debugging symbols packages not following common naming scheme
|
||||
if [ "$(dbg_package_name libstdc++6)" == "" ]; then
|
||||
if package_exists libstdc++6-8-dbg; then
|
||||
dbg_list="${dbg_list} libstdc++6-8-dbg"
|
||||
elif package_exists libstdc++6-7-dbg; then
|
||||
dbg_list="${dbg_list} libstdc++6-7-dbg"
|
||||
elif package_exists libstdc++6-6-dbg; then
|
||||
dbg_list="${dbg_list} libstdc++6-6-dbg"
|
||||
elif package_exists libstdc++6-5-dbg; then
|
||||
dbg_list="${dbg_list} libstdc++6-5-dbg"
|
||||
elif package_exists libstdc++6-4.9-dbg; then
|
||||
dbg_list="${dbg_list} libstdc++6-4.9-dbg"
|
||||
elif package_exists libstdc++6-4.8-dbg; then
|
||||
dbg_list="${dbg_list} libstdc++6-4.8-dbg"
|
||||
elif package_exists libstdc++6-4.7-dbg; then
|
||||
dbg_list="${dbg_list} libstdc++6-4.7-dbg"
|
||||
elif package_exists libstdc++6-4.6-dbg; then
|
||||
dbg_list="${dbg_list} libstdc++6-4.6-dbg"
|
||||
fi
|
||||
fi
|
||||
if [ "$(dbg_package_name libatk1.0-0)" == "" ]; then
|
||||
dbg_list="$dbg_list $(dbg_package_name libatk1.0)"
|
||||
fi
|
||||
if [ "$(dbg_package_name libpango1.0-0)" == "" ]; then
|
||||
dbg_list="$dbg_list $(dbg_package_name libpango1.0-dev)"
|
||||
fi
|
||||
else
|
||||
echo "Skipping debugging symbols."
|
||||
dbg_list=
|
||||
fi
|
||||
if [ "$do_inst_lib32" = "1" ]; then
|
||||
echo "Including 32-bit libraries."
|
||||
else
|
||||
echo "Skipping 32-bit libraries."
|
||||
lib32_list=
|
||||
fi
|
||||
if [ "$do_inst_arm" = "1" ]; then
|
||||
echo "Including ARM cross toolchain."
|
||||
else
|
||||
echo "Skipping ARM cross toolchain."
|
||||
arm_list=
|
||||
fi
|
||||
if [ "$do_inst_nacl" = "1" ]; then
|
||||
echo "Including NaCl, NaCl toolchain, NaCl ports dependencies."
|
||||
else
|
||||
echo "Skipping NaCl, NaCl toolchain, NaCl ports dependencies."
|
||||
nacl_list=
|
||||
fi
|
||||
filtered_backwards_compatible_list=
|
||||
if [ "$do_inst_backwards_compatible" = "1" ]; then
|
||||
echo "Including backwards compatible packages."
|
||||
for package in ${backwards_compatible_list}; do
|
||||
if package_exists ${package}; then
|
||||
filtered_backwards_compatible_list+=" ${package}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# The `sort -r -s -t: -k2` sorts all the :i386 packages to the front, to avoid
|
||||
# confusing dpkg-query (crbug.com/446172).
|
||||
packages="$(
|
||||
echo "${dev_list} ${lib_list} ${dbg_list} ${lib32_list} ${arm_list}" \
|
||||
"${nacl_list}" ${filtered_backwards_compatible_list} | tr " " "\n" | \
|
||||
sort -u | sort -r -s -t: -k2 | tr "\n" " "
|
||||
)"
|
||||
if [ 1 -eq "${do_quick_check-0}" ] ; then
|
||||
if ! missing_packages="$(dpkg-query -W -f ' ' ${packages} 2>&1)"; then
|
||||
# Distinguish between packages that actually aren't available to the
|
||||
# system (i.e. not in any repo) and packages that just aren't known to
|
||||
# dpkg (i.e. managed by apt).
|
||||
missing_packages="$(echo "${missing_packages}" | awk '{print $NF}')"
|
||||
not_installed=""
|
||||
unknown=""
|
||||
for p in ${missing_packages}; do
|
||||
if apt-cache show ${p} > /dev/null 2>&1; then
|
||||
not_installed="${p}\n${not_installed}"
|
||||
else
|
||||
unknown="${p}\n${unknown}"
|
||||
fi
|
||||
done
|
||||
if [ -n "${not_installed}" ]; then
|
||||
echo "WARNING: The following packages are not installed:"
|
||||
echo -e "${not_installed}" | sed -e "s/^/ /"
|
||||
fi
|
||||
if [ -n "${unknown}" ]; then
|
||||
echo "WARNING: The following packages are unknown to your system"
|
||||
echo "(maybe missing a repo or need to 'sudo apt-get update'):"
|
||||
echo -e "${unknown}" | sed -e "s/^/ /"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
if [ "$do_inst_lib32" = "1" ] || [ "$do_inst_nacl" = "1" ]; then
|
||||
sudo dpkg --add-architecture i386
|
||||
fi
|
||||
sudo apt-get update
|
||||
# We initially run "apt-get" with the --reinstall option and parse its output.
|
||||
# This way, we can find all the packages that need to be newly installed
|
||||
# without accidentally promoting any packages from "auto" to "manual".
|
||||
# We then re-run "apt-get" with just the list of missing packages.
|
||||
echo "Finding missing packages..."
|
||||
# Intentionally leaving $packages unquoted so it's more readable.
|
||||
echo "Packages required: " $packages
|
||||
echo
|
||||
new_list_cmd="sudo apt-get install --reinstall $(echo $packages)"
|
||||
if new_list="$(yes n | LANGUAGE=en LANG=C $new_list_cmd)"; then
|
||||
# We probably never hit this following line.
|
||||
echo "No missing packages, and the packages are up to date."
|
||||
elif [ $? -eq 1 ]; then
|
||||
# We expect apt-get to have exit status of 1.
|
||||
# This indicates that we cancelled the install with "yes n|".
|
||||
new_list=$(echo "$new_list" |
|
||||
sed -e '1,/The following NEW packages will be installed:/d;s/^ //;t;d')
|
||||
new_list=$(echo "$new_list" | sed 's/ *$//')
|
||||
if [ -z "$new_list" ] ; then
|
||||
echo "No missing packages, and the packages are up to date."
|
||||
else
|
||||
echo "Installing missing packages: $new_list."
|
||||
sudo apt-get install ${do_quietly-} ${new_list}
|
||||
fi
|
||||
echo
|
||||
else
|
||||
# An apt-get exit status of 100 indicates that a real error has occurred.
|
||||
# I am intentionally leaving out the '"'s around new_list_cmd,
|
||||
# as this makes it easier to cut and paste the output
|
||||
echo "The following command failed: " ${new_list_cmd}
|
||||
echo
|
||||
echo "It produces the following output:"
|
||||
yes n | $new_list_cmd || true
|
||||
echo
|
||||
echo "You will have to install the above packages yourself."
|
||||
echo
|
||||
exit 100
|
||||
fi
|
||||
# Install the Chrome OS default fonts. This must go after running
|
||||
# apt-get, since install-chromeos-fonts depends on curl.
|
||||
if [ "$do_inst_chromeos_fonts" != "0" ]; then
|
||||
echo
|
||||
echo "Installing Chrome OS fonts."
|
||||
dir=`echo $0 | sed -r -e 's/\/[^/]+$//'`
|
||||
if ! sudo $dir/linux/install-chromeos-fonts.py; then
|
||||
echo "ERROR: The installation of the Chrome OS default fonts failed."
|
||||
if [ `stat -f -c %T $dir` == "nfs" ]; then
|
||||
echo "The reason is that your repo is installed on a remote file system."
|
||||
else
|
||||
echo "This is expected if your repo is installed on a remote file system."
|
||||
fi
|
||||
echo "It is recommended to install your repo on a local file system."
|
||||
echo "You can skip the installation of the Chrome OS default founts with"
|
||||
echo "the command line option: --no-chromeos-fonts."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Skipping installation of Chrome OS fonts."
|
||||
fi
|
||||
echo "Installing locales."
|
||||
CHROMIUM_LOCALES="da_DK.UTF-8 fr_FR.UTF-8 he_IL.UTF-8 zh_TW.UTF-8"
|
||||
LOCALE_GEN=/etc/locale.gen
|
||||
if [ -e ${LOCALE_GEN} ]; then
|
||||
OLD_LOCALE_GEN="$(cat /etc/locale.gen)"
|
||||
for CHROMIUM_LOCALE in ${CHROMIUM_LOCALES}; do
|
||||
sudo sed -i "s/^# ${CHROMIUM_LOCALE}/${CHROMIUM_LOCALE}/" ${LOCALE_GEN}
|
||||
done
|
||||
# Regenerating locales can take a while, so only do it if we need to.
|
||||
if (echo "${OLD_LOCALE_GEN}" | cmp -s ${LOCALE_GEN}); then
|
||||
echo "Locales already up-to-date."
|
||||
else
|
||||
sudo locale-gen
|
||||
fi
|
||||
else
|
||||
for CHROMIUM_LOCALE in ${CHROMIUM_LOCALES}; do
|
||||
sudo locale-gen ${CHROMIUM_LOCALE}
|
||||
done
|
||||
fi
|
||||
@@ -163,7 +163,7 @@ if ((globalThis.process || binding.process).argv.includes("--profile-electron-in
|
||||
setImmediate: false
|
||||
},
|
||||
optimization: {
|
||||
minimize: env.mode === 'production',
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
|
||||
@@ -22,11 +22,6 @@ template("webpack_build") {
|
||||
"//electron/typings/internal-electron.d.ts",
|
||||
] + invoker.inputs
|
||||
|
||||
mode = "development"
|
||||
if (is_official_build) {
|
||||
mode = "production"
|
||||
}
|
||||
|
||||
args = [
|
||||
"--config",
|
||||
rebase_path(invoker.config_file),
|
||||
@@ -34,7 +29,6 @@ template("webpack_build") {
|
||||
"--output-path=" + rebase_path(get_path_info(invoker.out_file, "dir")),
|
||||
"--env.buildflags=" +
|
||||
rebase_path("$target_gen_dir/buildflags/buildflags.h"),
|
||||
"--env.mode=" + mode,
|
||||
]
|
||||
deps += [ "buildflags" ]
|
||||
|
||||
|
||||
@@ -143,17 +143,10 @@ static_library("chrome") {
|
||||
"//chrome/browser/platform_util.h",
|
||||
"//chrome/browser/ui/browser_dialogs.h",
|
||||
"//chrome/browser/ui/color_chooser.h",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper.cc",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper.h",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view.cc",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view.h",
|
||||
]
|
||||
|
||||
if (use_aura) {
|
||||
sources += [
|
||||
"//chrome/browser/platform_util_aura.cc",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view_aura.cc",
|
||||
]
|
||||
sources += [ "//chrome/browser/platform_util_aura.cc" ]
|
||||
|
||||
if (!is_win) {
|
||||
sources += [
|
||||
@@ -170,8 +163,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/media/webrtc/window_icon_util_mac.mm",
|
||||
"//chrome/browser/ui/cocoa/color_chooser_mac.h",
|
||||
"//chrome/browser/ui/cocoa/color_chooser_mac.mm",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.h",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.mm",
|
||||
]
|
||||
deps += [
|
||||
"//components/remote_cocoa/app_shim",
|
||||
@@ -217,6 +208,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/printing/print_view_manager_basic.h",
|
||||
"//chrome/browser/printing/printer_query.cc",
|
||||
"//chrome/browser/printing/printer_query.h",
|
||||
"//chrome/browser/printing/printing_message_filter.cc",
|
||||
"//chrome/browser/printing/printing_message_filter.h",
|
||||
"//chrome/browser/printing/printing_service.cc",
|
||||
"//chrome/browser/printing/printing_service.h",
|
||||
]
|
||||
|
||||
@@ -41,14 +41,14 @@ ipcMain.handle('bootstrap', (event) => {
|
||||
return isTrustedSender(event.sender) ? electronPath : null;
|
||||
});
|
||||
|
||||
async function createWindow (backgroundColor?: string) {
|
||||
async function createWindow () {
|
||||
await app.whenReady();
|
||||
|
||||
const options: Electron.BrowserWindowConstructorOptions = {
|
||||
width: 960,
|
||||
height: 620,
|
||||
autoHideMenuBar: true,
|
||||
backgroundColor,
|
||||
backgroundColor: '#2f3241',
|
||||
webPreferences: {
|
||||
preload: path.resolve(__dirname, 'preload.js'),
|
||||
contextIsolation: true,
|
||||
@@ -96,7 +96,7 @@ export const loadURL = async (appUrl: string) => {
|
||||
};
|
||||
|
||||
export const loadFile = async (appPath: string) => {
|
||||
mainWindow = await createWindow(appPath === 'index.html' ? '#2f3241' : undefined);
|
||||
mainWindow = await createWindow();
|
||||
mainWindow.loadFile(appPath);
|
||||
mainWindow.focus();
|
||||
};
|
||||
|
||||
@@ -59,7 +59,6 @@ an issue:
|
||||
* [Using Native Node.js Modules](tutorial/using-native-node-modules.md)
|
||||
* [Performance Strategies](tutorial/performance.md)
|
||||
* [Security Strategies](tutorial/security.md)
|
||||
* [Process Sandboxing](tutorial/sandbox.md)
|
||||
* [Accessibility](tutorial/accessibility.md)
|
||||
* [Manually Enabling Accessibility Features](tutorial/accessibility.md#manually-enabling-accessibility-features)
|
||||
* [Testing and Debugging](tutorial/application-debugging.md)
|
||||
@@ -69,7 +68,6 @@ an issue:
|
||||
* [Testing on Headless CI Systems (Travis, Jenkins)](tutorial/testing-on-headless-ci.md)
|
||||
* [DevTools Extension](tutorial/devtools-extension.md)
|
||||
* [Automated Testing with a Custom Driver](tutorial/automated-testing-with-a-custom-driver.md)
|
||||
* [REPL](tutorial/repl.md)
|
||||
* [Distribution](tutorial/application-distribution.md)
|
||||
* [Supported Platforms](tutorial/support.md#supported-platforms)
|
||||
* [Code Signing](tutorial/code-signing.md)
|
||||
@@ -128,8 +126,6 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
* [ipcMain](api/ipc-main.md)
|
||||
* [Menu](api/menu.md)
|
||||
* [MenuItem](api/menu-item.md)
|
||||
* [MessageChannelMain](api/message-channel-main.md)
|
||||
* [MessagePortMain](api/message-port-main.md)
|
||||
* [net](api/net.md)
|
||||
* [netLog](api/net-log.md)
|
||||
* [nativeTheme](api/native-theme.md)
|
||||
@@ -139,7 +135,6 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
* [protocol](api/protocol.md)
|
||||
* [screen](api/screen.md)
|
||||
* [session](api/session.md)
|
||||
* [ShareMenu](api/share-menu.md)
|
||||
* [systemPreferences](api/system-preferences.md)
|
||||
* [TouchBar](api/touch-bar.md)
|
||||
* [Tray](api/tray.md)
|
||||
@@ -148,15 +143,15 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
|
||||
### Modules for the Renderer Process (Web Page):
|
||||
|
||||
* [contextBridge](api/context-bridge.md)
|
||||
* [desktopCapturer](api/desktop-capturer.md)
|
||||
* [ipcRenderer](api/ipc-renderer.md)
|
||||
* [remote](api/remote.md)
|
||||
* [webFrame](api/web-frame.md)
|
||||
|
||||
### Modules for Both Processes:
|
||||
|
||||
* [clipboard](api/clipboard.md)
|
||||
* [crashReporter](api/crash-reporter.md)
|
||||
* [desktopCapturer](api/desktop-capturer.md)
|
||||
* [nativeImage](api/native-image.md)
|
||||
* [shell](api/shell.md)
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ Linux and Windows to define some accelerators.
|
||||
Use `Alt` instead of `Option`. The `Option` key only exists on macOS, whereas
|
||||
the `Alt` key is available on all platforms.
|
||||
|
||||
The `Super` (or `Meta`) key is mapped to the `Windows` key on Windows and Linux and
|
||||
The `Super` key is mapped to the `Windows` key on Windows and Linux and
|
||||
`Cmd` on macOS.
|
||||
|
||||
## Available modifiers
|
||||
@@ -48,7 +48,6 @@ The `Super` (or `Meta`) key is mapped to the `Windows` key on Windows and Linux
|
||||
* `AltGr`
|
||||
* `Shift`
|
||||
* `Super`
|
||||
* `Meta`
|
||||
|
||||
## Available key codes
|
||||
|
||||
|
||||
18
docs/api/app.md
Executable file → Normal file
18
docs/api/app.md
Executable file → Normal file
@@ -391,7 +391,7 @@ which contains more information about why the render process disappeared. It
|
||||
isn't always because it crashed. The `killed` boolean can be replaced by
|
||||
checking `reason === 'killed'` when you switch to that event.
|
||||
|
||||
### Event: 'render-process-gone'
|
||||
#### Event: 'render-process-gone'
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -406,14 +406,11 @@ Returns:
|
||||
* `oom` - Process ran out of memory
|
||||
* `launch-failed` - Process never successfully launched
|
||||
* `integrity-failure` - Windows code integrity checks failed
|
||||
* `exitCode` Integer - The exit code of the process, unless `reason` is
|
||||
`launch-failed`, in which case `exitCode` will be a platform-specific
|
||||
launch failure error code.
|
||||
|
||||
Emitted when the renderer process unexpectedly disappears. This is normally
|
||||
because it was crashed or killed.
|
||||
|
||||
### Event: 'child-process-gone'
|
||||
#### Event: 'child-process-gone'
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -753,8 +750,7 @@ Overrides the current application's name.
|
||||
|
||||
### `app.getLocale()`
|
||||
|
||||
Returns `String` - The current application locale, fetched using Chromium's `l10n_util` library.
|
||||
Possible return values are documented [here](https://source.chromium.org/chromium/chromium/src/+/master:ui/base/l10n/l10n_util.cc).
|
||||
Returns `String` - The current application locale. Possible return values are documented [here](locales.md).
|
||||
|
||||
To set the locale, you'll want to use a command line switch at app startup, which may be found [here](https://github.com/electron/electron/blob/master/docs/api/command-line-switches.md).
|
||||
|
||||
@@ -930,10 +926,6 @@ re-add a removed item to a custom category earlier than that will result in the
|
||||
entire custom category being omitted from the Jump List. The list of removed
|
||||
items can be obtained using `app.getJumpListSettings()`.
|
||||
|
||||
**Note:** The maximum length of a Jump List item's `description` property is
|
||||
260 characters. Beyond this limit, the item will not be added to the Jump
|
||||
List, nor will it be displayed.
|
||||
|
||||
Here's a very simple example of creating a custom Jump List:
|
||||
|
||||
```javascript
|
||||
@@ -1182,9 +1174,9 @@ For `infoType` equal to `basic`:
|
||||
|
||||
Using `basic` should be preferred if only basic information like `vendorId` or `driverId` is needed.
|
||||
|
||||
### `app.setBadgeCount([count])` _Linux_ _macOS_
|
||||
### `app.setBadgeCount(count)` _Linux_ _macOS_
|
||||
|
||||
* `count` Integer (optional) - If a value is provided, set the badge to the provided value otherwise, on macOS, display a plain white dot (e.g. unknown number of notifications). On Linux, if a value is not provided the badge will not display.
|
||||
* `count` Integer
|
||||
|
||||
Returns `Boolean` - Whether the call succeeded.
|
||||
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
# BrowserView
|
||||
|
||||
A `BrowserView` can be used to embed additional web content into a
|
||||
[`BrowserWindow`](browser-window.md). It is like a child window, except that it is positioned
|
||||
relative to its owning window. It is meant to be an alternative to the
|
||||
`webview` tag.
|
||||
|
||||
## Class: BrowserView
|
||||
|
||||
> Create and control views.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
A `BrowserView` can be used to embed additional web content into a
|
||||
[`BrowserWindow`](browser-window.md). It is like a child window, except that it is positioned
|
||||
relative to its owning window. It is meant to be an alternative to the
|
||||
`webview` tag.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -227,7 +227,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
unless hovered over in the top left of the window. These custom buttons prevent
|
||||
issues with mouse events that occur with the standard window toolbar buttons.
|
||||
**Note:** This option is currently experimental.
|
||||
* `trafficLightPosition` [Point](structures/point.md) (optional) - Set a custom position for the traffic light buttons. Can only be used with `titleBarStyle` set to `hidden`
|
||||
* `trafficLightPosition` [Point](structures/point.md) (optional) - Set a
|
||||
custom position for the traffic light buttons. Can only be used with
|
||||
`titleBarStyle` set to `hidden` or `customButtonsOnHover`.
|
||||
* `fullscreenWindowTitle` Boolean (optional) - Shows the title in the
|
||||
title bar in full screen mode on macOS for all `titleBarStyle` options.
|
||||
Default is `false`.
|
||||
@@ -265,12 +267,12 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
be the absolute file path to the script.
|
||||
When node integration is turned off, the preload script can reintroduce
|
||||
Node global symbols back to the global scope. See example
|
||||
[here](context-bridge.md#exposing-node-global-symbols).
|
||||
[here](process.md#event-loaded).
|
||||
* `sandbox` Boolean (optional) - If set, this will sandbox the renderer
|
||||
associated with the window, making it compatible with the Chromium
|
||||
OS-level sandbox and disabling the Node.js engine. This is not the same as
|
||||
the `nodeIntegration` option and the APIs available to the preload script
|
||||
are more limited. Read more about the option [here](../tutorial/sandbox.md).
|
||||
are more limited. Read more about the option [here](sandbox-option.md).
|
||||
* `enableRemoteModule` Boolean (optional) - Whether to enable the [`remote`](remote.md) module.
|
||||
Default is `false`.
|
||||
* `session` [Session](session.md#class-session) (optional) - Sets the session used by the
|
||||
@@ -337,7 +339,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
more details.
|
||||
* `contextIsolation` Boolean (optional) - Whether to run Electron APIs and
|
||||
the specified `preload` script in a separate JavaScript context. Defaults
|
||||
to `true`. The context that the `preload` script runs in will only have
|
||||
to `false`. The context that the `preload` script runs in will only have
|
||||
access to its own dedicated `document` and `window` globals, as well as
|
||||
its own set of JavaScript builtins (`Array`, `Object`, `JSON`, etc.),
|
||||
which are all invisible to the loaded content. The Electron API will only
|
||||
@@ -349,7 +351,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
context in the dev tools by selecting the 'Electron Isolated Context'
|
||||
entry in the combo box at the top of the Console tab.
|
||||
* `worldSafeExecuteJavaScript` Boolean (optional) - If true, values returned from `webFrame.executeJavaScript` will be sanitized to ensure JS values
|
||||
can't unsafely cross between worlds when using `contextIsolation`. Defaults to `true`. _Deprecated_
|
||||
can't unsafely cross between worlds when using `contextIsolation`. The default
|
||||
is `false`. In Electron 12, the default will be changed to `true`. _Deprecated_
|
||||
* `nativeWindowOpen` Boolean (optional) - Whether to use native
|
||||
`window.open()`. Defaults to `false`. Child windows will always have node
|
||||
integration disabled unless `nodeIntegrationInSubFrames` is true. **Note:** This option is currently
|
||||
@@ -722,94 +725,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-options).
|
||||
|
||||
#### `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-options).
|
||||
|
||||
#### `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:
|
||||
@@ -1050,7 +965,7 @@ Returns `Boolean` - Whether the window is in simple (pre-Lion) fullscreen mode.
|
||||
|
||||
Returns `Boolean` - Whether the window is in normal state (not maximized, not minimized, not in fullscreen mode).
|
||||
|
||||
#### `win.setAspectRatio(aspectRatio[, extraSize])`
|
||||
#### `win.setAspectRatio(aspectRatio[, extraSize])` _macOS_ _Linux_
|
||||
|
||||
* `aspectRatio` Float - The aspect ratio to maintain for some portion of the
|
||||
content view.
|
||||
@@ -1071,9 +986,6 @@ the player itself we would call this function with arguments of 16/9 and
|
||||
are within the content view--only that they exist. Sum any extra width and
|
||||
height areas you have within the overall content view.
|
||||
|
||||
The aspect ratio is not respected when window is resized programmingly with
|
||||
APIs like `win.setSize`.
|
||||
|
||||
#### `win.setBackgroundColor(backgroundColor)`
|
||||
|
||||
* `backgroundColor` String - Window's background color as a hexadecimal value,
|
||||
@@ -1386,7 +1298,7 @@ can be be used to listen to changes to tablet mode.
|
||||
|
||||
#### `win.getMediaSourceId()`
|
||||
|
||||
Returns `String` - Window id in the format of DesktopCapturerSource's id. For example "window:1324:0".
|
||||
Returns `String` - Window id in the format of DesktopCapturerSource's id. For example "window:1234:0".
|
||||
|
||||
More precisely the format is `window:id:other_id` where `id` is `HWND` on
|
||||
Windows, `CGWindowID` (`uint64_t`) on macOS and `Window` (`unsigned long`) on
|
||||
@@ -1404,8 +1316,6 @@ The native type of the handle is `HWND` on Windows, `NSView*` on macOS, and
|
||||
|
||||
* `message` Integer
|
||||
* `callback` Function
|
||||
* `wParam` any - The `wParam` provided to the WndProc
|
||||
* `lParam` any - The `lParam` provided to the WndProc
|
||||
|
||||
Hooks a windows message. The `callback` is called when
|
||||
the message is received in the WndProc.
|
||||
@@ -1458,7 +1368,7 @@ Returns `Boolean` - Whether the window's document has been edited.
|
||||
|
||||
Returns `Promise<NativeImage>` - Resolves with a [NativeImage](native-image.md)
|
||||
|
||||
Captures a snapshot of the page within `rect`. Omitting `rect` will capture the whole visible page. If the page is not visible, `rect` may be empty.
|
||||
Captures a snapshot of the page within `rect`. Omitting `rect` will capture the whole visible page.
|
||||
|
||||
#### `win.loadURL(url[, options])`
|
||||
|
||||
@@ -1829,12 +1739,13 @@ deprecated and will be removed in an upcoming version of macOS.
|
||||
|
||||
* `position` [Point](structures/point.md)
|
||||
|
||||
Set a custom position for the traffic light buttons. Can only be used with `titleBarStyle` set to `hidden`.
|
||||
Set a custom position for the traffic light buttons. Can only be used with
|
||||
`titleBarStyle` set to `hidden` or `customButtonsOnHover`.
|
||||
|
||||
#### `win.getTrafficLightPosition()` _macOS_
|
||||
|
||||
Returns `Point` - The current position for the traffic light buttons. Can only be used with `titleBarStyle`
|
||||
set to `hidden`.
|
||||
Returns `Point` - The current position for the traffic light buttons. Can only
|
||||
be used with `titleBarStyle` set to `hidden` or `customButtonsOnHover`.
|
||||
|
||||
#### `win.setTouchBar(touchBar)` _macOS_
|
||||
|
||||
@@ -1868,13 +1779,6 @@ Replacement API for setBrowserView supporting work with multi browser views.
|
||||
|
||||
* `browserView` [BrowserView](browser-view.md)
|
||||
|
||||
#### `win.setTopBrowserView(browserView)` _Experimental_
|
||||
|
||||
* `browserView` [BrowserView](browser-view.md)
|
||||
|
||||
Raises `browserView` above other `BrowserView`s attached to `win`.
|
||||
Throws an error if `browserView` is not attached to `win`.
|
||||
|
||||
#### `win.getBrowserViews()` _Experimental_
|
||||
|
||||
Returns `BrowserView[]` - an array of all BrowserViews that have been attached
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -80,12 +80,6 @@ This switch can not be used in `app.commandLine.appendSwitch` since it is parsed
|
||||
earlier than user's app is loaded, but you can set the `ELECTRON_ENABLE_LOGGING`
|
||||
environment variable to achieve the same effect.
|
||||
|
||||
### --force-fieldtrials=`trials`
|
||||
|
||||
Field trials to be forcefully enabled or disabled.
|
||||
|
||||
For example: `WebRTC-Audio-Red-For-Opus/Enabled/`
|
||||
|
||||
### --host-rules=`rules`
|
||||
|
||||
A comma-separated list of `rules` that control how hostnames are mapped.
|
||||
@@ -142,8 +136,7 @@ proxy server flags that are passed.
|
||||
|
||||
### --no-sandbox
|
||||
|
||||
Disables the Chromium [sandbox](https://www.chromium.org/developers/design-documents/sandbox).
|
||||
Forces renderer process and Chromium helper processes to run un-sandboxed.
|
||||
Disables Chromium sandbox, which is now enabled by default.
|
||||
Should only be used for testing.
|
||||
|
||||
### --proxy-bypass-list=`hosts`
|
||||
|
||||
@@ -33,7 +33,7 @@ page you load in your renderer executes code in this world.
|
||||
|
||||
### Isolated World
|
||||
|
||||
When `contextIsolation` is enabled in your `webPreferences` (this is the default behavior since Electron 12.0.0), your `preload` scripts run in an
|
||||
When `contextIsolation` is enabled in your `webPreferences`, your `preload` scripts run in an
|
||||
"Isolated World". You can read more about context isolation and what it affects in the
|
||||
[security](../tutorial/security.md#3-enable-context-isolation-for-remote-content) docs.
|
||||
|
||||
@@ -106,25 +106,7 @@ has been included below for completeness:
|
||||
| `Promise` | Complex | ✅ | ✅ | Promises are only proxied if they are the return value or exact parameter. Promises nested in arrays or objects will be dropped. |
|
||||
| `Function` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending classes or constructors will not work. |
|
||||
| [Cloneable Types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) | Simple | ✅ | ✅ | See the linked document on cloneable types |
|
||||
| `Element` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending custom elements will not work. |
|
||||
| `Symbol` | N/A | ❌ | ❌ | Symbols cannot be copied across contexts so they are dropped |
|
||||
|
||||
If the type you care about is not in the above table, it is probably not supported.
|
||||
|
||||
### Exposing Node Global Symbols
|
||||
|
||||
The `contextBridge` can be used by the preload script to give your renderer access to Node APIs.
|
||||
The table of supported types described above also applies to Node APIs that you expose through `contextBridge`.
|
||||
Please note that many Node APIs grant access to local system resources.
|
||||
Be very cautious about which globals and APIs you expose to untrusted remote content.
|
||||
|
||||
```javascript
|
||||
const { contextBridge } = require('electron')
|
||||
const crypto = require('crypto')
|
||||
contextBridge.exposeInMainWorld('nodeCrypto', {
|
||||
sha256sum (data) {
|
||||
const hash = crypto.createHash('sha256')
|
||||
hash.update(data)
|
||||
return hash.digest('hex')
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
@@ -45,8 +45,6 @@ The following events are available on instances of `Cookies`:
|
||||
|
||||
#### Event: 'changed'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `cookie` [Cookie](structures/cookie.md) - The cookie that was changed.
|
||||
* `cause` String - The cause of the change with one of the following values:
|
||||
|
||||
@@ -154,7 +154,7 @@ dialog.showOpenDialog(mainWindow, {
|
||||
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) (optional)
|
||||
* `options` Object
|
||||
* `title` String (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
|
||||
* `title` String (optional)
|
||||
* `defaultPath` String (optional) - Absolute directory path, absolute file
|
||||
path, or file name to use by default.
|
||||
* `buttonLabel` String (optional) - Custom label for the confirmation button, when
|
||||
@@ -185,7 +185,7 @@ The `filters` specifies an array of file types that can be displayed, see
|
||||
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) (optional)
|
||||
* `options` Object
|
||||
* `title` String (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
|
||||
* `title` String (optional)
|
||||
* `defaultPath` String (optional) - Absolute directory path, absolute file
|
||||
path, or file name to use by default.
|
||||
* `buttonLabel` String (optional) - Custom label for the confirmation button, when
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -15,7 +15,7 @@ extension capabilities.
|
||||
|
||||
Electron only supports loading unpacked extensions (i.e., `.crx` files do not
|
||||
work). Extensions are installed per-`session`. To load an extension, call
|
||||
[`ses.loadExtension`](session.md#sesloadextensionpath-options):
|
||||
[`ses.loadExtension`](session.md#sesloadextensionpath):
|
||||
|
||||
```js
|
||||
const { session } = require('electron')
|
||||
|
||||
@@ -82,11 +82,8 @@ win.show()
|
||||
* The `blur` filter only applies to the web page, so there is no way to apply
|
||||
blur effect to the content below the window (i.e. other applications open on
|
||||
the user's system).
|
||||
* The window will not be transparent when DevTools is opened.
|
||||
* On Windows operating systems,
|
||||
* transparent windows will not work when DWM is
|
||||
* On Windows operating systems, transparent windows will not work when DWM is
|
||||
disabled.
|
||||
* transparent windows can not be maximized using the Windows system menu or by double clicking the title bar. The reasoning behind this can be seen on [this pull request](https://github.com/electron/electron/pull/28207).
|
||||
* On Linux, users have to put `--enable-transparent-visuals --disable-gpu` in
|
||||
the command line to disable GPU and allow ARGB to make transparent window,
|
||||
this is caused by an upstream bug that [alpha channel doesn't work on some
|
||||
|
||||
@@ -62,9 +62,10 @@ included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
> **NOTE:** Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
>
|
||||
> Since the main process does not have support for DOM objects such as
|
||||
> special Electron objects is deprecated, and will begin throwing an exception
|
||||
> starting with Electron 9.
|
||||
|
||||
> **NOTE:** Since the main process does not have support for DOM objects such as
|
||||
> `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over
|
||||
> Electron's IPC to the main process, as the main process would have no way to decode
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
@@ -89,10 +90,11 @@ Algorithm][SCA], just like [`window.postMessage`][], so prototype chains will no
|
||||
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
> **NOTE:** Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
>
|
||||
> Since the main process does not have support for DOM objects such as
|
||||
> **NOTE**: Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects is deprecated, and will begin throwing an exception
|
||||
> starting with Electron 9.
|
||||
|
||||
> **NOTE:** Since the main process does not have support for DOM objects such as
|
||||
> `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over
|
||||
> Electron's IPC to the main process, as the main process would have no way to decode
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
@@ -132,10 +134,11 @@ Algorithm][SCA], just like [`window.postMessage`][], so prototype chains will no
|
||||
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
> **NOTE:** Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
>
|
||||
> Since the main process does not have support for DOM objects such as
|
||||
> **NOTE**: Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects is deprecated, and will begin throwing an exception
|
||||
> starting with Electron 9.
|
||||
|
||||
> **NOTE:** Since the main process does not have support for DOM objects such as
|
||||
> `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over
|
||||
> Electron's IPC to the main process, as the main process would have no way to decode
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
142
docs/api/locales.md
Normal file
142
docs/api/locales.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# Locales
|
||||
|
||||
> Locale values returned by `app.getLocale()`.
|
||||
|
||||
Electron uses Chromium's `l10n_util` library to fetch the locale. Possible
|
||||
values are listed below:
|
||||
|
||||
| Language Code | Language Name |
|
||||
|---------------|---------------|
|
||||
| af | Afrikaans |
|
||||
| am | Amharic |
|
||||
| ar | Arabic |
|
||||
| az | Azerbaijani |
|
||||
| be | Belarusian |
|
||||
| bg | Bulgarian |
|
||||
| bh | Bihari |
|
||||
| bn | Bengali |
|
||||
| br | Breton |
|
||||
| bs | Bosnian |
|
||||
| ca | Catalan |
|
||||
| co | Corsican |
|
||||
| cs | Czech |
|
||||
| cy | Welsh |
|
||||
| da | Danish |
|
||||
| de | German |
|
||||
| de-AT | German (Austria) |
|
||||
| de-CH | German (Switzerland) |
|
||||
| de-DE | German (Germany) |
|
||||
| el | Greek |
|
||||
| en | English |
|
||||
| en-AU | English (Australia) |
|
||||
| en-CA | English (Canada) |
|
||||
| en-GB | English (UK) |
|
||||
| en-NZ | English (New Zealand) |
|
||||
| en-US | English (US) |
|
||||
| en-ZA | English (South Africa) |
|
||||
| eo | Esperanto |
|
||||
| es | Spanish |
|
||||
| es-419 | Spanish (Latin America) |
|
||||
| et | Estonian |
|
||||
| eu | Basque |
|
||||
| fa | Persian |
|
||||
| fi | Finnish |
|
||||
| fil | Filipino |
|
||||
| fo | Faroese |
|
||||
| fr | French |
|
||||
| fr-CA | French (Canada) |
|
||||
| fr-CH | French (Switzerland) |
|
||||
| fr-FR | French (France) |
|
||||
| fy | Frisian |
|
||||
| ga | Irish |
|
||||
| gd | Scots Gaelic |
|
||||
| gl | Galician |
|
||||
| gn | Guarani |
|
||||
| gu | Gujarati |
|
||||
| ha | Hausa |
|
||||
| haw | Hawaiian |
|
||||
| he | Hebrew |
|
||||
| hi | Hindi |
|
||||
| hr | Croatian |
|
||||
| hu | Hungarian |
|
||||
| hy | Armenian |
|
||||
| ia | Interlingua |
|
||||
| id | Indonesian |
|
||||
| is | Icelandic |
|
||||
| it | Italian |
|
||||
| it-CH | Italian (Switzerland) |
|
||||
| it-IT | Italian (Italy) |
|
||||
| ja | Japanese |
|
||||
| jw | Javanese |
|
||||
| ka | Georgian |
|
||||
| kk | Kazakh |
|
||||
| km | Cambodian |
|
||||
| kn | Kannada |
|
||||
| ko | Korean |
|
||||
| ku | Kurdish |
|
||||
| ky | Kyrgyz |
|
||||
| la | Latin |
|
||||
| ln | Lingala |
|
||||
| lo | Laothian |
|
||||
| lt | Lithuanian |
|
||||
| lv | Latvian |
|
||||
| mk | Macedonian |
|
||||
| ml | Malayalam |
|
||||
| mn | Mongolian |
|
||||
| mo | Moldavian |
|
||||
| mr | Marathi |
|
||||
| ms | Malay |
|
||||
| mt | Maltese |
|
||||
| nb | Norwegian (Bokmal) |
|
||||
| ne | Nepali |
|
||||
| nl | Dutch |
|
||||
| nn | Norwegian (Nynorsk) |
|
||||
| no | Norwegian |
|
||||
| oc | Occitan |
|
||||
| om | Oromo |
|
||||
| or | Oriya |
|
||||
| pa | Punjabi |
|
||||
| pl | Polish |
|
||||
| ps | Pashto |
|
||||
| pt | Portuguese |
|
||||
| pt-BR | Portuguese (Brazil) |
|
||||
| pt-PT | Portuguese (Portugal) |
|
||||
| qu | Quechua |
|
||||
| rm | Romansh |
|
||||
| ro | Romanian |
|
||||
| ru | Russian |
|
||||
| sd | Sindhi |
|
||||
| sh | Serbo-Croatian |
|
||||
| si | Sinhalese |
|
||||
| sk | Slovak |
|
||||
| sl | Slovenian |
|
||||
| sn | Shona |
|
||||
| so | Somali |
|
||||
| sq | Albanian |
|
||||
| sr | Serbian |
|
||||
| st | Sesotho |
|
||||
| su | Sundanese |
|
||||
| sv | Swedish |
|
||||
| sw | Swahili |
|
||||
| ta | Tamil |
|
||||
| te | Telugu |
|
||||
| tg | Tajik |
|
||||
| th | Thai |
|
||||
| ti | Tigrinya |
|
||||
| tk | Turkmen |
|
||||
| to | Tonga |
|
||||
| tr | Turkish |
|
||||
| tt | Tatar |
|
||||
| tw | Twi |
|
||||
| ug | Uighur |
|
||||
| uk | Ukrainian |
|
||||
| ur | Urdu |
|
||||
| uz | Uzbek |
|
||||
| vi | Vietnamese |
|
||||
| xh | Xhosa |
|
||||
| yi | Yiddish |
|
||||
| yo | Yoruba |
|
||||
| zh | Chinese |
|
||||
| zh-CN | Chinese (Simplified) |
|
||||
| zh-TW | Chinese (Traditional) |
|
||||
| zu | Zulu |
|
||||
@@ -1,5 +1,3 @@
|
||||
# Menu
|
||||
|
||||
## Class: Menu
|
||||
|
||||
> Create native application menus and context menus.
|
||||
|
||||
@@ -9,15 +9,12 @@ channel messaging.
|
||||
|
||||
## Class: MessageChannelMain
|
||||
|
||||
> Channel interface for channel messaging in the main process.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
// Main process
|
||||
const { MessageChannelMain } = require('electron')
|
||||
const { port1, port2 } = new MessageChannelMain()
|
||||
w.webContents.postMessage('port', null, [port2])
|
||||
port1.postMessage({ some: 'message' })
|
||||
|
||||
@@ -14,8 +14,6 @@ channel messaging.
|
||||
|
||||
## Class: MessagePortMain
|
||||
|
||||
> Port interface for channel messaging in the main process.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
### Instance Methods
|
||||
|
||||
10
docs/api/modernization/overview.md
Normal file
10
docs/api/modernization/overview.md
Normal file
@@ -0,0 +1,10 @@
|
||||
## Modernization
|
||||
|
||||
The Electron team is currently undergoing an initiative to modernize our API in a few concrete ways. These include: updating our modules to use idiomatic JS properties instead of separate `getPropertyX` and `setPropertyX`, converting callbacks to promises, and removing some other anti-patterns present in our APIs. The current status of the Promise initiative can be tracked in the [promisification](promisification.md) tracking file.
|
||||
|
||||
As we work to perform these updates, we seek to create the least disruptive amount of change at any given time, so as many changes as possible will be introduced in a backward compatible manner and deprecated after enough time has passed to give users a chance to upgrade their API calls.
|
||||
|
||||
This document and its child documents will be updated to reflect the latest status of our API changes.
|
||||
|
||||
* [Promisification](promisification.md)
|
||||
* [Property Updates](property-updates.md)
|
||||
42
docs/api/modernization/promisification.md
Normal file
42
docs/api/modernization/promisification.md
Normal file
@@ -0,0 +1,42 @@
|
||||
## Promisification
|
||||
|
||||
The Electron team recently underwent an initiative to convert callback-based APIs to Promise-based ones. See converted functions below:
|
||||
|
||||
- [app.getFileIcon(path[, options], callback)](https://github.com/electron/electron/blob/master/docs/api/app.md#getFileIcon)
|
||||
- [contents.capturePage([rect, ]callback)](https://github.com/electron/electron/blob/master/docs/api/web-contents.md#capturePage)
|
||||
- [contents.executeJavaScript(code[, userGesture, callback])](https://github.com/electron/electron/blob/master/docs/api/web-contents.md#executeJavaScript)
|
||||
- [contents.printToPDF(options, callback)](https://github.com/electron/electron/blob/master/docs/api/web-contents.md#printToPDF)
|
||||
- [contents.savePage(fullPath, saveType, callback)](https://github.com/electron/electron/blob/master/docs/api/web-contents.md#savePage)
|
||||
- [contentTracing.getCategories(callback)](https://github.com/electron/electron/blob/master/docs/api/content-tracing.md#getCategories)
|
||||
- [contentTracing.startRecording(options, callback)](https://github.com/electron/electron/blob/master/docs/api/content-tracing.md#startRecording)
|
||||
- [contentTracing.stopRecording(resultFilePath, callback)](https://github.com/electron/electron/blob/master/docs/api/content-tracing.md#stopRecording)
|
||||
- [contentTracing.getTraceBufferUsage(callback)](https://github.com/electron/electron/blob/master/docs/api/content-tracing.md#getTraceBufferUsage)
|
||||
- [cookies.flushStore(callback)](https://github.com/electron/electron/blob/master/docs/api/cookies.md#flushStore)
|
||||
- [cookies.get(filter, callback)](https://github.com/electron/electron/blob/master/docs/api/cookies.md#get)
|
||||
- [cookies.remove(url, name, callback)](https://github.com/electron/electron/blob/master/docs/api/cookies.md#remove)
|
||||
- [cookies.set(details, callback)](https://github.com/electron/electron/blob/master/docs/api/cookies.md#set)
|
||||
- [debugger.sendCommand(method[, commandParams, callback])](https://github.com/electron/electron/blob/master/docs/api/debugger.md#sendCommand)
|
||||
- [desktopCapturer.getSources(options, callback)](https://github.com/electron/electron/blob/master/docs/api/desktop-capturer.md#getSources)
|
||||
- [dialog.showOpenDialog([browserWindow, ]options[, callback])](https://github.com/electron/electron/blob/master/docs/api/dialog.md#showOpenDialog)
|
||||
- [dialog.showSaveDialog([browserWindow, ]options[, callback])](https://github.com/electron/electron/blob/master/docs/api/dialog.md#showSaveDialog)
|
||||
- [inAppPurchase.purchaseProduct(productID, quantity, callback)](https://github.com/electron/electron/blob/master/docs/api/in-app-purchase.md#purchaseProduct)
|
||||
- [inAppPurchase.getProducts(productIDs, callback)](https://github.com/electron/electron/blob/master/docs/api/in-app-purchase.md#getProducts)
|
||||
- [dialog.showMessageBox([browserWindow, ]options[, callback])](https://github.com/electron/electron/blob/master/docs/api/dialog.md#showMessageBox)
|
||||
- [dialog.showCertificateTrustDialog([browserWindow, ]options, callback)](https://github.com/electron/electron/blob/master/docs/api/dialog.md#showCertificateTrustDialog)
|
||||
- [netLog.stopLogging([callback])](https://github.com/electron/electron/blob/master/docs/api/net-log.md#stopLogging)
|
||||
- [protocol.isProtocolHandled(scheme, callback)](https://github.com/electron/electron/blob/master/docs/api/protocol.md#isProtocolHandled)
|
||||
- [ses.clearHostResolverCache([callback])](https://github.com/electron/electron/blob/master/docs/api/session.md#clearHostResolverCache)
|
||||
- [ses.clearStorageData([options, callback])](https://github.com/electron/electron/blob/master/docs/api/session.md#clearStorageData)
|
||||
- [ses.setProxy(config, callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#setProxy)
|
||||
- [ses.resolveProxy(url, callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#resolveProxy)
|
||||
- [ses.getCacheSize(callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#getCacheSize)
|
||||
- [ses.clearAuthCache(options[, callback])](https://github.com/electron/electron/blob/master/docs/api/session.md#clearAuthCache)
|
||||
- [ses.clearCache(callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#clearCache)
|
||||
- [ses.getBlobData(identifier, callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#getBlobData)
|
||||
- [shell.openExternal(url[, options, callback])](https://github.com/electron/electron/blob/master/docs/api/shell.md#openExternal)
|
||||
- [webFrame.executeJavaScript(code[, userGesture, callback])](https://github.com/electron/electron/blob/master/docs/api/web-frame.md#executeJavaScript)
|
||||
- [webFrame.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture, callback])](https://github.com/electron/electron/blob/master/docs/api/web-frame.md#executeJavaScriptInIsolatedWorld)
|
||||
- [webviewTag.capturePage([rect, ]callback)](https://github.com/electron/electron/blob/master/docs/api/webview-tag.md#capturePage)
|
||||
- [webviewTag.executeJavaScript(code[, userGesture, callback])](https://github.com/electron/electron/blob/master/docs/api/webview-tag.md#executeJavaScript)
|
||||
- [webviewTag.printToPDF(options, callback)](https://github.com/electron/electron/blob/master/docs/api/webview-tag.md#printToPDF)
|
||||
- [win.capturePage([rect, ]callback)](https://github.com/electron/electron/blob/master/docs/api/browser-window.md#capturePage)
|
||||
41
docs/api/modernization/property-updates.md
Normal file
41
docs/api/modernization/property-updates.md
Normal file
@@ -0,0 +1,41 @@
|
||||
## Property Updates
|
||||
|
||||
The Electron team is currently undergoing an initiative to convert separate getter and setter functions in Electron to bespoke properties with `get` and `set` functionality. During this transition period, both the new properties and old getters and setters of these functions will work correctly and be documented.
|
||||
|
||||
## Candidates
|
||||
|
||||
* `BrowserWindow`
|
||||
* `menubarVisible`
|
||||
* `crashReporter` module
|
||||
* `uploadToServer`
|
||||
* `webFrame` modules
|
||||
* `zoomFactor`
|
||||
* `zoomLevel`
|
||||
* `audioMuted`
|
||||
* `<webview>`
|
||||
* `zoomFactor`
|
||||
* `zoomLevel`
|
||||
* `audioMuted`
|
||||
|
||||
## Converted Properties
|
||||
|
||||
* `app` module
|
||||
* `accessibilitySupport`
|
||||
* `applicationMenu`
|
||||
* `badgeCount`
|
||||
* `name`
|
||||
* `DownloadItem` class
|
||||
* `savePath`
|
||||
* `BrowserWindow` module
|
||||
* `autoHideMenuBar`
|
||||
* `resizable`
|
||||
* `maximizable`
|
||||
* `minimizable`
|
||||
* `fullscreenable`
|
||||
* `movable`
|
||||
* `closable`
|
||||
* `backgroundThrottling`
|
||||
* `NativeImage`
|
||||
* `isMacTemplateImage`
|
||||
* `SystemPreferences` module
|
||||
* `appLevelAppearance`
|
||||
@@ -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
|
||||
|
||||
@@ -42,6 +43,19 @@ In sandboxed renderers the `process` object contains only a subset of the APIs:
|
||||
Emitted when Electron has loaded its internal initialization script and is
|
||||
beginning to load the web page or the main script.
|
||||
|
||||
It can be used by the preload script to add removed Node global symbols back to
|
||||
the global scope when node integration is turned off:
|
||||
|
||||
```javascript
|
||||
// preload.js
|
||||
const _setImmediate = setImmediate
|
||||
const _clearImmediate = clearImmediate
|
||||
process.once('loaded', () => {
|
||||
global.setImmediate = _setImmediate
|
||||
global.clearImmediate = _clearImmediate
|
||||
})
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### `process.defaultApp` _Readonly_
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
182
docs/api/sandbox-option.md
Normal file
182
docs/api/sandbox-option.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# `sandbox` Option
|
||||
|
||||
> Create a browser window with a sandboxed renderer. With this
|
||||
option enabled, the renderer must communicate via IPC to the main process in order to access node APIs.
|
||||
|
||||
One of the key security features of Chromium is that all blink rendering/JavaScript
|
||||
code is executed within a sandbox. This sandbox uses OS-specific features to ensure
|
||||
that exploits in the renderer process cannot harm the system.
|
||||
|
||||
In other words, when the sandbox is enabled, the renderers can only make changes
|
||||
to the system by delegating tasks to the main process via IPC.
|
||||
[Here's](https://www.chromium.org/developers/design-documents/sandbox) more
|
||||
information about the sandbox.
|
||||
|
||||
Since a major feature in Electron is the ability to run Node.js in the
|
||||
renderer process (making it easier to develop desktop applications using web
|
||||
technologies), the sandbox is disabled by electron. This is because
|
||||
most Node.js APIs require system access. `require()` for example, is not
|
||||
possible without file system permissions, which are not available in a sandboxed
|
||||
environment.
|
||||
|
||||
Usually this is not a problem for desktop applications since the code is always
|
||||
trusted, but it makes Electron less secure than Chromium for displaying
|
||||
untrusted web content. For applications that require more security, the
|
||||
`sandbox` flag will force Electron to spawn a classic Chromium renderer that is
|
||||
compatible with the sandbox.
|
||||
|
||||
A sandboxed renderer doesn't have a Node.js environment running and doesn't
|
||||
expose Node.js JavaScript APIs to client code. The only exception is the preload script,
|
||||
which has access to a subset of the Electron renderer API.
|
||||
|
||||
Another difference is that sandboxed renderers don't modify any of the default
|
||||
JavaScript APIs. Consequently, some APIs such as `window.open` will work as they
|
||||
do in Chromium (i.e. they do not return a [`BrowserWindowProxy`](browser-window-proxy.md)).
|
||||
|
||||
## Example
|
||||
|
||||
To create a sandboxed window, pass `sandbox: true` to `webPreferences`:
|
||||
|
||||
```js
|
||||
let win
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
sandbox: true
|
||||
}
|
||||
})
|
||||
win.loadURL('http://google.com')
|
||||
})
|
||||
```
|
||||
|
||||
In the above code the [`BrowserWindow`](browser-window.md) that was created has Node.js disabled and can communicate
|
||||
only via IPC. The use of this option stops Electron from creating a Node.js runtime in the renderer. Also,
|
||||
within this new window `window.open` follows the native behavior (by default Electron creates a [`BrowserWindow`](browser-window.md)
|
||||
and returns a proxy to this via `window.open`).
|
||||
|
||||
[`app.enableSandbox`](app.md#appenablesandbox) can be used to force `sandbox: true` for all `BrowserWindow` instances.
|
||||
|
||||
```js
|
||||
let win
|
||||
app.enableSandbox()
|
||||
app.whenReady().then(() => {
|
||||
// no need to pass `sandbox: true` since `app.enableSandbox()` was called.
|
||||
win = new BrowserWindow()
|
||||
win.loadURL('http://google.com')
|
||||
})
|
||||
```
|
||||
|
||||
## Preload
|
||||
|
||||
An app can make customizations to sandboxed renderers using a preload script.
|
||||
Here's an example:
|
||||
|
||||
```js
|
||||
let win
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
sandbox: true,
|
||||
preload: path.join(app.getAppPath(), 'preload.js')
|
||||
}
|
||||
})
|
||||
win.loadURL('http://google.com')
|
||||
})
|
||||
```
|
||||
|
||||
and preload.js:
|
||||
|
||||
```js
|
||||
// This file is loaded whenever a javascript context is created. It runs in a
|
||||
// private scope that can access a subset of Electron renderer APIs. Without
|
||||
// contextIsolation enabled, it's possible to accidentally leak privileged
|
||||
// globals like ipcRenderer to web content.
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
const defaultWindowOpen = window.open
|
||||
|
||||
window.open = function customWindowOpen (url, ...args) {
|
||||
ipcRenderer.send('report-window-open', location.origin, url, args)
|
||||
return defaultWindowOpen(url + '?from_electron=1', ...args)
|
||||
}
|
||||
```
|
||||
|
||||
Important things to notice in the preload script:
|
||||
|
||||
- Even though the sandboxed renderer doesn't have Node.js running, it still has
|
||||
access to a limited node-like environment: `Buffer`, `process`, `setImmediate`,
|
||||
`clearImmediate` and `require` are available.
|
||||
- The preload script must be contained in a single script, but it is possible to have
|
||||
complex preload code composed with multiple modules by using a tool like
|
||||
webpack or browserify. An example of using browserify is below.
|
||||
|
||||
To create a browserify bundle and use it as a preload script, something like
|
||||
the following should be used:
|
||||
|
||||
```sh
|
||||
browserify preload/index.js \
|
||||
-x electron \
|
||||
--insert-global-vars=__filename,__dirname -o preload.js
|
||||
```
|
||||
|
||||
The `-x` flag should be used with any required module that is already exposed in
|
||||
the preload scope, and tells browserify to use the enclosing `require` function
|
||||
for it. `--insert-global-vars` will ensure that `process`, `Buffer` and
|
||||
`setImmediate` are also taken from the enclosing scope(normally browserify
|
||||
injects code for those).
|
||||
|
||||
Currently the `require` function provided in the preload scope exposes the
|
||||
following modules:
|
||||
|
||||
- `electron`
|
||||
- `crashReporter`
|
||||
- `desktopCapturer`
|
||||
- `ipcRenderer`
|
||||
- `nativeImage`
|
||||
- `webFrame`
|
||||
- `events`
|
||||
- `timers`
|
||||
- `url`
|
||||
|
||||
More may be added as needed to expose more Electron APIs in the sandbox.
|
||||
|
||||
## Rendering untrusted content
|
||||
|
||||
Rendering untrusted content in Electron is still somewhat uncharted territory,
|
||||
though some apps are finding success (e.g. Beaker Browser). Our goal is to get
|
||||
as close to Chrome as we can in terms of the security of sandboxed content, but
|
||||
ultimately we will always be behind due to a few fundamental issues:
|
||||
|
||||
1. We do not have the dedicated resources or expertise that Chromium has to
|
||||
apply to the security of its product. We do our best to make use of what we
|
||||
have, to inherit everything we can from Chromium, and to respond quickly to
|
||||
security issues, but Electron cannot be as secure as Chromium without the
|
||||
resources that Chromium is able to dedicate.
|
||||
2. Some security features in Chrome (such as Safe Browsing and Certificate
|
||||
Transparency) require a centralized authority and dedicated servers, both of
|
||||
which run counter to the goals of the Electron project. As such, we disable
|
||||
those features in Electron, at the cost of the associated security they
|
||||
would otherwise bring.
|
||||
3. There is only one Chromium, whereas there are many thousands of apps built
|
||||
on Electron, all of which behave slightly differently. Accounting for those
|
||||
differences can yield a huge possibility space, and make it challenging to
|
||||
ensure the security of the platform in unusual use cases.
|
||||
4. We can't push security updates to users directly, so we rely on app vendors
|
||||
to upgrade the version of Electron underlying their app in order for
|
||||
security updates to reach users.
|
||||
|
||||
Here are some things to consider before rendering untrusted content:
|
||||
|
||||
- A preload script can accidentally leak privileged APIs to untrusted code,
|
||||
unless [`contextIsolation`](../tutorial/security.md#3-enable-context-isolation-for-remote-content)
|
||||
is also enabled.
|
||||
- Some bug in the V8 engine may allow malicious code to access the renderer
|
||||
preload APIs, effectively granting full access to the system through the
|
||||
`remote` module. Therefore, it is highly recommended to [disable the `remote`
|
||||
module](../tutorial/security.md#15-disable-the-remote-module).
|
||||
If disabling is not feasible, you should selectively [filter the `remote`
|
||||
module](../tutorial/security.md#16-filter-the-remote-module).
|
||||
- While we make our best effort to backport Chromium security fixes to older
|
||||
versions of Electron, we do not make a guarantee that every fix will be
|
||||
backported. Your best chance at staying secure is to be on the latest stable
|
||||
version of Electron.
|
||||
@@ -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)).
|
||||
|
||||
@@ -215,15 +215,15 @@ app.whenReady().then(() => {
|
||||
enableBlinkFeatures: 'Serial'
|
||||
}
|
||||
})
|
||||
win.webContents.session.on('select-serial-port', (event, portList, callback) => {
|
||||
win.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {
|
||||
event.preventDefault()
|
||||
const selectedPort = portList.find((device) => {
|
||||
return device.vendorId === 0x2341 && device.productId === 0x0043
|
||||
return device.vendorId === '9025' && device.productId === '67'
|
||||
})
|
||||
if (!selectedPort) {
|
||||
callback('')
|
||||
} else {
|
||||
callback(result1.portId)
|
||||
callback(selectedPort.portId)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -501,6 +501,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.
|
||||
@@ -512,7 +513,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')
|
||||
@@ -528,28 +531,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
|
||||
})
|
||||
```
|
||||
|
||||
@@ -743,13 +750,9 @@ will not work on non-persistent (in-memory) sessions.
|
||||
|
||||
**Note:** On macOS and Windows 10 this word will be removed from the OS custom dictionary as well
|
||||
|
||||
#### `ses.loadExtension(path[, options])`
|
||||
#### `ses.loadExtension(path)`
|
||||
|
||||
* `path` String - Path to a directory containing an unpacked Chrome extension
|
||||
* `options` Object (optional)
|
||||
* `allowFileAccess` Boolean - Whether to allow the extension to read local files over `file://`
|
||||
protocol and inject content scripts into `file://` pages. This is required e.g. for loading
|
||||
devtools extensions on `file://` URLs. Defaults to false.
|
||||
|
||||
Returns `Promise<Extension>` - resolves when the extension is loaded.
|
||||
|
||||
@@ -772,11 +775,7 @@ const { app, session } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
app.on('ready', async () => {
|
||||
await session.defaultSession.loadExtension(
|
||||
path.join(__dirname, 'react-devtools'),
|
||||
// allowFileAccess is required to load the devtools extension on file:// URLs.
|
||||
{ allowFileAccess: true }
|
||||
)
|
||||
await session.defaultSession.loadExtension(path.join(__dirname, 'react-devtools'))
|
||||
// Note that in order to use the React DevTools extension, you'll need to
|
||||
// download and unzip a copy of the extension.
|
||||
})
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
# ShareMenu
|
||||
## Class: ShareMenu
|
||||
|
||||
> Create share menu on macOS.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
The `ShareMenu` class creates [Share Menu][share-menu] on macOS, which can be
|
||||
used to share information from the current context to apps, social media
|
||||
@@ -7,12 +11,6 @@ accounts, and other services.
|
||||
For including the share menu as a submenu of other menus, please use the
|
||||
`shareMenu` role of [`MenuItem`](menu-item.md).
|
||||
|
||||
## Class: ShareMenu
|
||||
|
||||
> Create share menu on macOS.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
### `new ShareMenu(sharingItem)`
|
||||
|
||||
* `sharingItem` SharingItem - The item to share.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -19,7 +19,3 @@
|
||||
property set then its `type` is assumed to be `tasks`. If the `name` property
|
||||
is set but the `type` property is omitted then the `type` is assumed to be
|
||||
`custom`.
|
||||
|
||||
**Note:** The maximum length of a Jump List item's `description` property is
|
||||
260 characters. Beyond this limit, the item will not be added to the Jump
|
||||
List, nor will it be displayed.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* `title` String (optional) - The text to be displayed for the item in the Jump List.
|
||||
Should only be set if `type` is `task`.
|
||||
* `description` String (optional) - Description of the task (displayed in a tooltip).
|
||||
Should only be set if `type` is `task`. Maximum length 260 characters.
|
||||
Should only be set if `type` is `task`.
|
||||
* `iconPath` String (optional) - The absolute path to an icon to be displayed in a
|
||||
Jump List, which can be an arbitrary resource file that contains an icon
|
||||
(e.g. `.ico`, `.exe`, `.dll`). You can usually specify `process.execPath` to
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# UploadFile Object
|
||||
|
||||
* `type` 'file' - `file`.
|
||||
* `type` String - `file`.
|
||||
* `filePath` String - Path of file to be uploaded.
|
||||
* `offset` Integer - Defaults to `0`.
|
||||
* `length` Integer - Number of bytes to read from `offset`.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# UploadRawData Object
|
||||
|
||||
* `type` 'rawData' - `rawData`.
|
||||
* `type` String - `rawData`.
|
||||
* `bytes` Buffer - Data to be uploaded.
|
||||
|
||||
@@ -130,8 +130,6 @@ This is necessary for events such as `NSUserDefaultsDidChangeNotification`.
|
||||
* `userInfo` Record<String, unknown>
|
||||
* `object` String
|
||||
|
||||
Returns `Number` - The ID of this subscription
|
||||
|
||||
Same as `subscribeNotification`, but uses `NSWorkspace.sharedWorkspace.notificationCenter`.
|
||||
This is necessary for events such as `NSWorkspaceDidActivateApplicationNotification`.
|
||||
|
||||
@@ -435,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.
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# TouchBar
|
||||
|
||||
## Class: TouchBar
|
||||
|
||||
> Create TouchBar layouts for native macOS applications
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# Tray
|
||||
|
||||
## Class: Tray
|
||||
|
||||
> Add icons and context menus to the system's notification area.
|
||||
|
||||
@@ -195,29 +195,30 @@ 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#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`.
|
||||
* `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
|
||||
@@ -402,9 +403,6 @@ Returns:
|
||||
* `oom` - Process ran out of memory
|
||||
* `launch-failed` - Process never successfully launched
|
||||
* `integrity-failure` - Windows code integrity checks failed
|
||||
* `exitCode` Integer - The exit code of the process, unless `reason` is
|
||||
`launch-failed`, in which case `exitCode` will be a platform-specific
|
||||
launch failure error code.
|
||||
|
||||
Emitted when the renderer process unexpectedly disappears. This is normally
|
||||
because it was crashed or killed.
|
||||
@@ -642,8 +640,15 @@ Returns:
|
||||
* `isEditable` Boolean - Whether the context is editable.
|
||||
* `selectionText` String - Text of the selection that the context menu was
|
||||
invoked on.
|
||||
* `titleText` String - Title or alt text of the selection that the context
|
||||
was invoked on.
|
||||
* `titleText` String - Title text of the selection that the context menu was
|
||||
invoked on.
|
||||
* `altText` String - Alt text of the selection that the context menu was
|
||||
invoked on.
|
||||
* `suggestedFilename` String - Suggested filename to be used when saving file through 'Save
|
||||
Link As' option of context menu.
|
||||
* `selectionRect` [Rectangle](structures/rectangle.md) - Rect representing the coordinates in the document space of the selection.
|
||||
* `selectionStartOffset` Number - Start position of the selection text.
|
||||
* `referrerPolicy` [Referrer](structures/referrer.md) - The referrer policy of the frame on which the menu is invoked.
|
||||
* `misspelledWord` String - The misspelled word under the cursor, if any.
|
||||
* `dictionarySuggestions` String[] - An array of suggested words to show the
|
||||
user to replace the `misspelledWord`. Only available if there is a misspelled
|
||||
@@ -653,8 +658,9 @@ Returns:
|
||||
* `inputFieldType` String - If the context menu was invoked on an input
|
||||
field, the type of that field. Possible values are `none`, `plainText`,
|
||||
`password`, `other`.
|
||||
* `spellcheckEnabled` Boolean - If the context is editable, whether or not spellchecking is enabled.
|
||||
* `menuSourceType` String - Input source that invoked the context menu.
|
||||
Can be `none`, `mouse`, `keyboard`, `touch` or `touchMenu`.
|
||||
Can be `none`, `mouse`, `keyboard`, `touch`, `touchMenu`, `longPress`, `longTap`, `touchHandle`, `stylus`, `adjustSelection`, or `adjustSelectionReset`.
|
||||
* `mediaFlags` Object - The flags for the media element the context menu was
|
||||
invoked on.
|
||||
* `inError` Boolean - Whether the media element has crashed.
|
||||
@@ -666,16 +672,22 @@ Returns:
|
||||
visible.
|
||||
* `canToggleControls` Boolean - Whether the media element's controls are
|
||||
toggleable.
|
||||
* `canPrint` Boolean - Whether the media element can be printed.
|
||||
* `canSave` Boolean - Whether or not the media element can be downloaded.
|
||||
* `canShowPictureInPicture` Boolean - Whether the media element can show picture-in-picture.
|
||||
* `isShowingPictureInPicture` Boolean - Whether the media element is currently showing picture-in-picture.
|
||||
* `canRotate` Boolean - Whether the media element can be rotated.
|
||||
* `canLoop` Boolean - Whether the media element can be looped.
|
||||
* `editFlags` Object - These flags indicate whether the renderer believes it
|
||||
is able to perform the corresponding action.
|
||||
* `canUndo` Boolean - Whether the renderer believes it can undo.
|
||||
* `canRedo` Boolean - Whether the renderer believes it can redo.
|
||||
* `canCut` Boolean - Whether the renderer believes it can cut.
|
||||
* `canCopy` Boolean - Whether the renderer believes it can copy
|
||||
* `canCopy` Boolean - Whether the renderer believes it can copy.
|
||||
* `canPaste` Boolean - Whether the renderer believes it can paste.
|
||||
* `canDelete` Boolean - Whether the renderer believes it can delete.
|
||||
* `canSelectAll` Boolean - Whether the renderer believes it can select all.
|
||||
* `canEditRichly` Boolean - Whether the renderer believes it can edit text richly.
|
||||
|
||||
Emitted when there is a new context menu that needs to be handled.
|
||||
|
||||
@@ -1169,7 +1181,6 @@ Ignore application menu shortcuts while this web contents is focused.
|
||||
* `url` String - The _resolved_ version of the URL passed to `window.open()`. e.g. opening a window with `window.open('foo')` will yield something like `https://the-origin/the/current/path/foo`.
|
||||
* `frameName` String - Name of the window provided in `window.open()`
|
||||
* `features` String - Comma separated list of window features provided to `window.open()`.
|
||||
|
||||
Returns `{action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}` - `deny` cancels the creation of the new
|
||||
window. `allow` will allow the new window to be created. Specifying `overrideBrowserWindowOptions` allows customization of the created window.
|
||||
Returning an unrecognized value such as a null, undefined, or an object
|
||||
@@ -1306,7 +1317,8 @@ Inserts `text` to the focused element.
|
||||
* `text` String - Content to be searched, must not be empty.
|
||||
* `options` Object (optional)
|
||||
* `forward` Boolean (optional) - Whether to search forward or backward, defaults to `true`.
|
||||
* `findNext` Boolean (optional) - Whether to begin a new text finding session with this request. Should be `true` for initial requests, and `false` for follow-up requests. Defaults to `false`.
|
||||
* `findNext` Boolean (optional) - Whether the operation is first request or a follow up,
|
||||
defaults to `false`.
|
||||
* `matchCase` Boolean (optional) - Whether search should be case-sensitive,
|
||||
defaults to `false`.
|
||||
|
||||
@@ -1467,7 +1479,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`:
|
||||
|
||||
@@ -1661,7 +1673,8 @@ included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
> **NOTE**: Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
> special Electron objects is deprecated, and will begin throwing an exception
|
||||
> starting with Electron 9.
|
||||
|
||||
The renderer process can handle the message by listening to `channel` with the
|
||||
[`ipcRenderer`](ipc-renderer.md) module.
|
||||
@@ -1697,9 +1710,7 @@ app.whenReady().then(() => {
|
||||
|
||||
#### `contents.sendToFrame(frameId, channel, ...args)`
|
||||
|
||||
* `frameId` Integer | [number, number] - the ID of the frame to send to, or a
|
||||
pair of `[processId, frameId]` if the frame is in a different process to the
|
||||
main frame.
|
||||
* `frameId` Integer | [number, number]
|
||||
* `channel` String
|
||||
* `...args` any[]
|
||||
|
||||
@@ -1709,8 +1720,9 @@ Send an asynchronous message to a specific frame in a renderer process via
|
||||
chains will not be included. Sending Functions, Promises, Symbols, WeakMaps, or
|
||||
WeakSets will throw an exception.
|
||||
|
||||
> **NOTE:** Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
> **NOTE**: Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects is deprecated, and will begin throwing an exception
|
||||
> starting with Electron 9.
|
||||
|
||||
The renderer process can handle the message by listening to `channel` with the
|
||||
[`ipcRenderer`](ipc-renderer.md) module.
|
||||
|
||||
@@ -63,8 +63,7 @@ These methods can be accessed from the `webFrameMain` module:
|
||||
instances (`frame.routingId`) and are also passed by frame
|
||||
specific `WebContents` navigation events (e.g. `did-frame-navigate`).
|
||||
|
||||
Returns `WebFrameMain | undefined` - A frame with the given process and routing IDs,
|
||||
or `undefined` if there is no WebFrameMain associated with the given IDs.
|
||||
Returns `WebFrameMain` - A frame with the given process and routing IDs.
|
||||
|
||||
## Class: WebFrameMain
|
||||
|
||||
@@ -90,47 +89,6 @@ this limitation.
|
||||
|
||||
Returns `boolean` - Whether the reload was initiated successfully. Only results in `false` when the frame has no history.
|
||||
|
||||
#### `frame.send(channel, ...args)`
|
||||
|
||||
* `channel` String
|
||||
* `...args` any[]
|
||||
|
||||
Send an asynchronous message to the renderer process via `channel`, along with
|
||||
arguments. Arguments will be serialized with the [Structured Clone
|
||||
Algorithm][SCA], just like [`postMessage`][], so prototype chains will not be
|
||||
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
The renderer process can handle the message by listening to `channel` with the
|
||||
[`ipcRenderer`](ipc-renderer.md) module.
|
||||
|
||||
#### `frame.postMessage(channel, message, [transfer])`
|
||||
|
||||
* `channel` String
|
||||
* `message` any
|
||||
* `transfer` MessagePortMain[] (optional)
|
||||
|
||||
Send a message to the renderer process, optionally transferring ownership of
|
||||
zero or more [`MessagePortMain`][] objects.
|
||||
|
||||
The transferred `MessagePortMain` objects will be available in the renderer
|
||||
process by accessing the `ports` property of the emitted event. When they
|
||||
arrive in the renderer, they will be native DOM `MessagePort` objects.
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
// Main process
|
||||
const { port1, port2 } = new MessageChannelMain()
|
||||
webContents.mainFrame.postMessage('port', { message: 'hello' }, [port1])
|
||||
|
||||
// Renderer process
|
||||
ipcRenderer.on('port', (e, msg) => {
|
||||
const [port] = e.ports
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
### Instance Properties
|
||||
|
||||
#### `frame.url` _Readonly_
|
||||
|
||||
@@ -51,8 +51,6 @@ The following methods are available on instances of `WebRequest`:
|
||||
* `url` String
|
||||
* `method` String
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
@@ -96,8 +94,6 @@ Some examples of valid `urls`:
|
||||
* `url` String
|
||||
* `method` String
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
@@ -125,8 +121,6 @@ The `callback` has to be called with a `response` object.
|
||||
* `url` String
|
||||
* `method` String
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
@@ -147,8 +141,6 @@ response are visible by the time this listener is fired.
|
||||
* `url` String
|
||||
* `method` String
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
@@ -181,8 +173,6 @@ The `callback` has to be called with a `response` object.
|
||||
* `url` String
|
||||
* `method` String
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
@@ -207,8 +197,6 @@ and response headers are available.
|
||||
* `url` String
|
||||
* `method` String
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
@@ -234,8 +222,6 @@ redirect is about to occur.
|
||||
* `url` String
|
||||
* `method` String
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
@@ -259,8 +245,6 @@ completed.
|
||||
* `url` String
|
||||
* `method` String
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Electron's `webview` tag is based on [Chromium's `webview`][chrome-webview], which
|
||||
is undergoing dramatic architectural changes. This impacts the stability of `webviews`,
|
||||
including rendering, navigation, and event routing. We currently recommend to not
|
||||
use the `webview` tag and to consider alternatives, like `iframe`, [Electron's `BrowserView`](browser-view.md),
|
||||
use the `webview` tag and to consider alternatives, like `iframe`, Electron's `BrowserView`,
|
||||
or an architecture that avoids embedded content altogether.
|
||||
|
||||
## Enabling
|
||||
@@ -515,7 +515,8 @@ Inserts `text` to the focused element.
|
||||
* `text` String - Content to be searched, must not be empty.
|
||||
* `options` Object (optional)
|
||||
* `forward` Boolean (optional) - Whether to search forward or backward, defaults to `true`.
|
||||
* `findNext` Boolean (optional) - Whether to begin a new text finding session with this request. Should be `true` for initial requests, and `false` for follow-up requests. Defaults to `false`.
|
||||
* `findNext` Boolean (optional) - Whether the operation is first request or a follow up,
|
||||
defaults to `false`.
|
||||
* `matchCase` Boolean (optional) - Whether search should be case-sensitive,
|
||||
defaults to `false`.
|
||||
|
||||
@@ -965,4 +966,4 @@ Emitted when DevTools is closed.
|
||||
Emitted when DevTools is focused / opened.
|
||||
|
||||
[runtime-enabled-features]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70
|
||||
[chrome-webview]: https://developer.chrome.com/docs/extensions/reference/webviewTag/
|
||||
[chrome-webview]: https://developer.chrome.com/apps/tags/webview
|
||||
|
||||
@@ -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
|
||||
@@ -83,9 +83,9 @@ const mainWindow = new BrowserWindow()
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
if (url.startsWith('https://github.com/')) {
|
||||
return { action: 'allow' }
|
||||
return true
|
||||
}
|
||||
return { action: 'deny' }
|
||||
return false
|
||||
})
|
||||
|
||||
mainWindow.webContents.on('did-create-window', (childWindow) => {
|
||||
|
||||
@@ -12,22 +12,6 @@ This document uses the following convention to categorize breaking changes:
|
||||
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
|
||||
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
|
||||
|
||||
## Planned Breaking API Changes (14.0)
|
||||
|
||||
### API Changed: `window.(open)`
|
||||
|
||||
The optional parameter `frameName` will no longer set the title of the window. This now follows the specification described by the [native documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#parameters) under the corresponding parameter `windowName`.
|
||||
|
||||
If you were using this parameter to set the title of a window, you can instead use [win.setTitle(title)](https://www.electronjs.org/docs/api/browser-window#winsettitletitle).
|
||||
|
||||
### Removed: `worldSafeExecuteJavaScript`
|
||||
|
||||
In Electron 14, `worldSafeExecuteJavaScript` will be removed. There is no alternative, please
|
||||
ensure your code works with this property enabled. It has been enabled by default since Electron
|
||||
12.
|
||||
|
||||
You will be affected by this change if you use either `webFrame.executeJavaScript` or `webFrame.executeJavaScriptInIsolatedWorld`. You will need to ensure that values returned by either of those methods are supported by the [Context Bridge API](api/context-bridge.md#parameter--error--return-type-support) as these methods use the same value passing semantics.
|
||||
|
||||
## Planned Breaking API Changes (13.0)
|
||||
|
||||
### API Changed: `session.setPermissionCheckHandler(handler)`
|
||||
@@ -108,13 +92,11 @@ session.defaultSession.getAllExtensions()
|
||||
### Removed: methods in `systemPreferences`
|
||||
|
||||
The following `systemPreferences` methods have been deprecated:
|
||||
|
||||
* `systemPreferences.isDarkMode()`
|
||||
* `systemPreferences.isInvertedColorScheme()`
|
||||
* `systemPreferences.isHighContrastColorScheme()`
|
||||
|
||||
Use the following `nativeTheme` properties instead:
|
||||
|
||||
* `nativeTheme.shouldUseDarkColors`
|
||||
* `nativeTheme.shouldUseInvertedColorScheme`
|
||||
* `nativeTheme.shouldUseHighContrastColors`
|
||||
@@ -144,15 +126,6 @@ Chromium has removed support for Flash, and so we must follow suit. See
|
||||
Chromium's [Flash Roadmap](https://www.chromium.org/flash-roadmap) for more
|
||||
details.
|
||||
|
||||
### Default Changed: `worldSafeExecuteJavaScript` defaults to `true`
|
||||
|
||||
In Electron 12, `worldSafeExecuteJavaScript` will be enabled by default. To restore
|
||||
the previous behavior, `worldSafeExecuteJavaScript: false` must be specified in WebPreferences.
|
||||
Please note that setting this option to `false` is **insecure**.
|
||||
|
||||
This option will be removed in Electron 14 so please migrate your code to support the default
|
||||
value.
|
||||
|
||||
### Default Changed: `contextIsolation` defaults to `true`
|
||||
|
||||
In Electron 12, `contextIsolation` will be enabled by default. To restore
|
||||
@@ -160,9 +133,6 @@ the previous behavior, `contextIsolation: false` must be specified in WebPrefere
|
||||
|
||||
We [recommend having contextIsolation enabled](https://github.com/electron/electron/blob/master/docs/tutorial/security.md#3-enable-context-isolation-for-remote-content) for the security of your application.
|
||||
|
||||
Another implication is that `require()` cannot be used in the renderer process unless
|
||||
`nodeIntegration` is `true` and `contextIsolation` is `false`.
|
||||
|
||||
For more details see: https://github.com/electron/electron/issues/23506
|
||||
|
||||
### Removed: `crashReporter.getCrashesDirectory()`
|
||||
@@ -586,7 +556,6 @@ limits are now fixed at a minimum of 0.25 and a maximum of 5.0, as defined
|
||||
### Deprecated events in `systemPreferences`
|
||||
|
||||
The following `systemPreferences` events have been deprecated:
|
||||
|
||||
* `inverted-color-scheme-changed`
|
||||
* `high-contrast-color-scheme-changed`
|
||||
|
||||
@@ -604,13 +573,11 @@ nativeTheme.on('updated', () => { /* ... */ })
|
||||
### Deprecated: methods in `systemPreferences`
|
||||
|
||||
The following `systemPreferences` methods have been deprecated:
|
||||
|
||||
* `systemPreferences.isDarkMode()`
|
||||
* `systemPreferences.isInvertedColorScheme()`
|
||||
* `systemPreferences.isHighContrastColorScheme()`
|
||||
|
||||
Use the following `nativeTheme` properties instead:
|
||||
|
||||
* `nativeTheme.shouldUseDarkColors`
|
||||
* `nativeTheme.shouldUseInvertedColorScheme`
|
||||
* `nativeTheme.shouldUseHighContrastColors`
|
||||
@@ -731,55 +698,6 @@ Note that `webkitdirectory` no longer exposes the path to the selected folder.
|
||||
If you require the path to the selected folder rather than the folder contents,
|
||||
see the `dialog.showOpenDialog` API ([link](https://github.com/electron/electron/blob/master/docs/api/dialog.md#dialogshowopendialogbrowserwindow-options)).
|
||||
|
||||
### API Changed: Callback-based versions of promisified APIs
|
||||
|
||||
Electron 5 and Electron 6 introduced Promise-based versions of existing
|
||||
asynchronous APIs and deprecated their older, callback-based counterparts.
|
||||
In Electron 7, all deprecated callback-based APIs are now removed.
|
||||
|
||||
These functions now only return Promises:
|
||||
|
||||
* `app.getFileIcon()` [#15742](https://github.com/electron/electron/pull/15742)
|
||||
* `app.dock.show()` [#16904](https://github.com/electron/electron/pull/16904)
|
||||
* `contentTracing.getCategories()` [#16583](https://github.com/electron/electron/pull/16583)
|
||||
* `contentTracing.getTraceBufferUsage()` [#16600](https://github.com/electron/electron/pull/16600)
|
||||
* `contentTracing.startRecording()` [#16584](https://github.com/electron/electron/pull/16584)
|
||||
* `contentTracing.stopRecording()` [#16584](https://github.com/electron/electron/pull/16584)
|
||||
* `contents.executeJavaScript()` [#17312](https://github.com/electron/electron/pull/17312)
|
||||
* `cookies.flushStore()` [#16464](https://github.com/electron/electron/pull/16464)
|
||||
* `cookies.get()` [#16464](https://github.com/electron/electron/pull/16464)
|
||||
* `cookies.remove()` [#16464](https://github.com/electron/electron/pull/16464)
|
||||
* `cookies.set()` [#16464](https://github.com/electron/electron/pull/16464)
|
||||
* `debugger.sendCommand()` [#16861](https://github.com/electron/electron/pull/16861)
|
||||
* `dialog.showCertificateTrustDialog()` [#17181](https://github.com/electron/electron/pull/17181)
|
||||
* `inAppPurchase.getProducts()` [#17355](https://github.com/electron/electron/pull/17355)
|
||||
* `inAppPurchase.purchaseProduct()`[#17355](https://github.com/electron/electron/pull/17355)
|
||||
* `netLog.stopLogging()` [#16862](https://github.com/electron/electron/pull/16862)
|
||||
* `session.clearAuthCache()` [#17259](https://github.com/electron/electron/pull/17259)
|
||||
* `session.clearCache()` [#17185](https://github.com/electron/electron/pull/17185)
|
||||
* `session.clearHostResolverCache()` [#17229](https://github.com/electron/electron/pull/17229)
|
||||
* `session.clearStorageData()` [#17249](https://github.com/electron/electron/pull/17249)
|
||||
* `session.getBlobData()` [#17303](https://github.com/electron/electron/pull/17303)
|
||||
* `session.getCacheSize()` [#17185](https://github.com/electron/electron/pull/17185)
|
||||
* `session.resolveProxy()` [#17222](https://github.com/electron/electron/pull/17222)
|
||||
* `session.setProxy()` [#17222](https://github.com/electron/electron/pull/17222)
|
||||
* `shell.openExternal()` [#16176](https://github.com/electron/electron/pull/16176)
|
||||
* `webContents.loadFile()` [#15855](https://github.com/electron/electron/pull/15855)
|
||||
* `webContents.loadURL()` [#15855](https://github.com/electron/electron/pull/15855)
|
||||
* `webContents.hasServiceWorker()` [#16535](https://github.com/electron/electron/pull/16535)
|
||||
* `webContents.printToPDF()` [#16795](https://github.com/electron/electron/pull/16795)
|
||||
* `webContents.savePage()` [#16742](https://github.com/electron/electron/pull/16742)
|
||||
* `webFrame.executeJavaScript()` [#17312](https://github.com/electron/electron/pull/17312)
|
||||
* `webFrame.executeJavaScriptInIsolatedWorld()` [#17312](https://github.com/electron/electron/pull/17312)
|
||||
* `webviewTag.executeJavaScript()` [#17312](https://github.com/electron/electron/pull/17312)
|
||||
* `win.capturePage()` [#15743](https://github.com/electron/electron/pull/15743)
|
||||
|
||||
These functions now have two forms, synchronous and Promise-based asynchronous:
|
||||
|
||||
* `dialog.showMessageBox()`/`dialog.showMessageBoxSync()` [#17298](https://github.com/electron/electron/pull/17298)
|
||||
* `dialog.showOpenDialog()`/`dialog.showOpenDialogSync()` [#16973](https://github.com/electron/electron/pull/16973)
|
||||
* `dialog.showSaveDialog()`/`dialog.showSaveDialogSync()` [#17054](https://github.com/electron/electron/pull/17054)
|
||||
|
||||
## Planned Breaking API Changes (6.0)
|
||||
|
||||
### API Changed: `win.setMenu(null)` is now `win.removeMenu()`
|
||||
@@ -791,6 +709,19 @@ win.setMenu(null)
|
||||
win.removeMenu()
|
||||
```
|
||||
|
||||
### API Changed: `contentTracing.getTraceBufferUsage()` is now a promise
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
contentTracing.getTraceBufferUsage((percentage, value) => {
|
||||
// do something
|
||||
})
|
||||
// Replace with
|
||||
contentTracing.getTraceBufferUsage().then(infoObject => {
|
||||
// infoObject has percentage and value fields
|
||||
})
|
||||
```
|
||||
|
||||
### API Changed: `electron.screen` in the renderer process should be accessed via `remote`
|
||||
|
||||
```js
|
||||
@@ -929,31 +860,6 @@ webFrame.setSpellCheckProvider('en-US', {
|
||||
})
|
||||
```
|
||||
|
||||
### API Changed: `webContents.getZoomLevel` and `webContents.getZoomFactor` are now synchronous
|
||||
|
||||
`webContents.getZoomLevel` and `webContents.getZoomFactor` no longer take callback parameters,
|
||||
instead directly returning their number values.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
webContents.getZoomLevel((level) => {
|
||||
console.log(level)
|
||||
})
|
||||
// Replace with
|
||||
const level = webContents.getZoomLevel()
|
||||
console.log(level)
|
||||
```
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
webContents.getZoomFactor((factor) => {
|
||||
console.log(factor)
|
||||
})
|
||||
// Replace with
|
||||
const factor = webContents.getZoomFactor()
|
||||
console.log(factor)
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (4.0)
|
||||
|
||||
The following list includes the breaking API changes made in Electron 4.0.
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# Build Instructions
|
||||
|
||||
Follow the guidelines below for building **Electron itself**, for the purposes of creating custom Electron binaries. For bundling and distributing your app code with the prebuilt Electron binaries, see the [application distribution][application-distribution] guide.
|
||||
|
||||
[application-distribution]: ../tutorial/application-distribution.md
|
||||
Follow the guidelines below for building Electron.
|
||||
|
||||
## Platform prerequisites
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# Build Instructions (Linux)
|
||||
|
||||
Follow the guidelines below for building **Electron itself** on Linux, for the purposes of creating custom Electron binaries. For bundling and distributing your app code with the prebuilt Electron binaries, see the [application distribution][application-distribution] guide.
|
||||
|
||||
[application-distribution]: ../tutorial/application-distribution.md
|
||||
Follow the guidelines below for building Electron on Linux.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -57,15 +55,6 @@ $ sudo dnf install clang dbus-devel gtk3-devel libnotify-devel \
|
||||
nss-devel python-dbusmock openjdk-8-jre
|
||||
```
|
||||
|
||||
On Arch Linux / Manjaro, install the following libraries:
|
||||
|
||||
```sh
|
||||
$ sudo pacman -Syu base-devel clang libdbus gtk2 libnotify \
|
||||
libgnome-keyring alsa-lib libcap libcups libxtst \
|
||||
libxss nss gcc-multilib curl gperf bison \
|
||||
python2 python-dbusmock jdk8-openjdk
|
||||
```
|
||||
|
||||
Other distributions may offer similar packages for installation via package
|
||||
managers such as pacman. Or one can compile from source code.
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# Build Instructions (macOS)
|
||||
|
||||
Follow the guidelines below for building **Electron itself** on macOS, for the purposes of creating custom Electron binaries. For bundling and distributing your app code with the prebuilt Electron binaries, see the [application distribution][application-distribution] guide.
|
||||
|
||||
[application-distribution]: ../tutorial/application-distribution.md
|
||||
Follow the guidelines below for building Electron on macOS.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -44,7 +42,7 @@ $ pip install pyobjc
|
||||
If you're developing Electron and don't plan to redistribute your
|
||||
custom Electron build, you may skip this section.
|
||||
|
||||
Official Electron builds are built with [Xcode 12.2](https://download.developer.apple.com/Developer_Tools/Xcode_12.2/Xcode_12.2.xip), and the macOS 11.0 SDK. Building with a newer SDK works too, but the releases currently use the 11.0 SDK.
|
||||
Official Electron builds are built with [Xcode 9.4.1](http://adcdownload.apple.com/Developer_Tools/Xcode_9.4.1/Xcode_9.4.1.xip), and the macOS 10.13 SDK. Building with a newer SDK works too, but the releases currently use the 10.13 SDK.
|
||||
|
||||
## Building Electron
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# Build Instructions (Windows)
|
||||
|
||||
Follow the guidelines below for building **Electron itself** on Windows, for the purposes of creating custom Electron binaries. For bundling and distributing your app code with the prebuilt Electron binaries, see the [application distribution][application-distribution] guide.
|
||||
|
||||
[application-distribution]: ../tutorial/application-distribution.md
|
||||
Follow the guidelines below for building Electron on Windows.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
||||
@@ -33,7 +33,8 @@ contributing, and more. Please use the issue tracker for bugs only!
|
||||
To submit a bug report:
|
||||
|
||||
When opening a new issue in the [`electron/electron` issue tracker](https://github.com/electron/electron/issues/new/choose), users
|
||||
will be presented with a template that should be filled in.
|
||||
will be presented with [a template](https://github.com/electron/electron/blob/master/.github/ISSUE_TEMPLATE/Bug_report.md)
|
||||
that should be filled in.
|
||||
|
||||
If you believe that you have found a bug in Electron, please fill out the template
|
||||
to the best of your ability.
|
||||
|
||||
@@ -100,5 +100,7 @@ script/ - The set of all scripts Electron runs for a variety of purposes.
|
||||
└── uploaders/ - Uploads various release-related files during release.
|
||||
```
|
||||
|
||||
* **tools** - Helper scripts used by GN files.
|
||||
* Scripts put here should never be invoked by users directly, unlike those in `script`.
|
||||
* **typings** - TypeScript typings for Electron's internal code.
|
||||
* **vendor** - Source code for some third party dependencies.
|
||||
|
||||
@@ -7,9 +7,12 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>Drag the boxes below to somewhere in your OS (Finder/Explorer, Desktop, etc.) to copy an example markdown file.</p>
|
||||
<div style="border:2px solid black;border-radius:3px;padding:5px;display:inline-block" draggable="true" id="drag1">Drag me - File 1</div>
|
||||
<div style="border:2px solid black;border-radius:3px;padding:5px;display:inline-block" draggable="true" id="drag2">Drag me - File 2</div>
|
||||
<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>
|
||||
|
||||
@@ -1,28 +1,21 @@
|
||||
const { app, BrowserWindow, ipcMain, nativeImage, NativeImage } = require('electron')
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const https = require('https')
|
||||
const fs = require('fs');
|
||||
const http = require('http');
|
||||
|
||||
function createWindow() {
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
const iconName = path.join(__dirname, 'iconForDragAndDrop.png');
|
||||
const icon = fs.createWriteStream(iconName);
|
||||
|
||||
// Create a new file to copy - you can also copy existing files.
|
||||
fs.writeFileSync(path.join(__dirname, 'drag-and-drop-1.md'), '# First file to test drag and drop')
|
||||
fs.writeFileSync(path.join(__dirname, 'drag-and-drop-2.md'), '# Second file to test drag and drop')
|
||||
|
||||
https.get('https://img.icons8.com/ios/452/drag-and-drop.png', (response) => {
|
||||
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);
|
||||
});
|
||||
|
||||
@@ -30,8 +23,8 @@ app.whenReady().then(createWindow)
|
||||
|
||||
ipcMain.on('ondragstart', (event, filePath) => {
|
||||
event.sender.startDrag({
|
||||
file: path.join(__dirname, filePath),
|
||||
icon: iconName,
|
||||
file: filePath,
|
||||
icon: `${process.cwd()}/${iconName}`
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
startDrag: (fileName) => {
|
||||
ipcRenderer.send('ondragstart', fileName)
|
||||
}
|
||||
})
|
||||
@@ -1,9 +1,9 @@
|
||||
document.getElementById('drag1').ondragstart = (event) => {
|
||||
event.preventDefault()
|
||||
window.electron.startDrag('drag-and-drop-1.md')
|
||||
}
|
||||
const { ipcRenderer } = require('electron')
|
||||
const fs = require('fs')
|
||||
|
||||
document.getElementById('drag2').ondragstart = (event) => {
|
||||
document.getElementById('drag').ondragstart = (event) => {
|
||||
const fileName = 'drag-and-drop.md'
|
||||
fs.writeFileSync(fileName, '# Test drag and drop');
|
||||
event.preventDefault()
|
||||
window.electron.startDrag('drag-and-drop-2.md')
|
||||
ipcRenderer.send('ondragstart', process.cwd() + `/${fileName}`)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
@@ -26,18 +25,16 @@ function createWindow () {
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('darkMode', {
|
||||
toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
|
||||
system: () => ipcRenderer.invoke('dark-mode:system')
|
||||
})
|
||||
@@ -1,9 +1,11 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
|
||||
const isDarkMode = await window.darkMode.toggle()
|
||||
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 window.darkMode.system()
|
||||
await ipcRenderer.invoke('dark-mode:system')
|
||||
document.getElementById('theme-source').innerHTML = 'System'
|
||||
})
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>Right click the dock icon to see the custom menu options.</p>
|
||||
<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>
|
||||
|
||||
@@ -4,6 +4,9 @@ function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
@@ -24,9 +27,7 @@ const dockMenu = Menu.buildFromTemplate([
|
||||
])
|
||||
|
||||
app.whenReady().then(() => {
|
||||
if (process.platform === 'darwin') {
|
||||
app.dock.setMenu(dockMenu)
|
||||
}
|
||||
app.dock.setMenu(dockMenu)
|
||||
}).then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using Node.js <span id="node-version"></span>,
|
||||
Chromium <span id="chrome-version"></span>,
|
||||
and Electron <span id="electron-version"></span>.
|
||||
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>
|
||||
|
||||
@@ -1,27 +1,18 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
@@ -29,3 +20,8 @@ app.on('window-all-closed', () => {
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const replaceText = (selector, text) => {
|
||||
const element = document.getElementById(selector)
|
||||
if (element) element.innerText = text
|
||||
}
|
||||
|
||||
for (const type of ['chrome', 'node', 'electron']) {
|
||||
replaceText(`${type}-version`, process.versions[type])
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
|
||||
These are the guidelines for writing Electron documentation.
|
||||
|
||||
## Headings
|
||||
## Titles
|
||||
|
||||
* Each page must have a single `#`-level title at the top.
|
||||
* Chapters in the same page must have `##`-level headings.
|
||||
* Sub-chapters need to increase the number of `#` in the heading according to
|
||||
* Chapters in the same page must have `##`-level titles.
|
||||
* Sub-chapters need to increase the number of `#` in the title according to
|
||||
their nesting depth.
|
||||
* The page's title must follow [APA title case][title-case].
|
||||
* All chapters must follow [APA sentence case][sentence-case].
|
||||
* All words in the page's title must be capitalized, except for conjunctions
|
||||
like "of" and "and" .
|
||||
* Only the first word of a chapter title must be capitalized.
|
||||
|
||||
Using `Quick Start` as example:
|
||||
|
||||
@@ -43,20 +44,12 @@ For API references, there are exceptions to this rule.
|
||||
|
||||
## Markdown rules
|
||||
|
||||
This repository uses the [`markdownlint`][markdownlint] package to enforce consistent
|
||||
Markdown styling. For the exact rules, see the `.markdownlint.json` file in the root
|
||||
folder.
|
||||
|
||||
There are a few style guidelines that aren't covered by the linter rules:
|
||||
|
||||
<!--TODO(erickzhao): make sure this matches with the lint:markdownlint task-->
|
||||
* Use `sh` instead of `cmd` in code blocks (due to the syntax highlighter).
|
||||
* Keep line lengths between 80 and 100 characters if possible for readability
|
||||
purposes.
|
||||
* Lines should be wrapped at 80 columns.
|
||||
* 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.
|
||||
* For unordered lists, use asterisks instead of dashes
|
||||
|
||||
## Picking words
|
||||
|
||||
@@ -67,15 +60,14 @@ There are a few style guidelines that aren't covered by the linter rules:
|
||||
|
||||
The following rules only apply to the documentation of APIs.
|
||||
|
||||
### Title and description
|
||||
### Page title
|
||||
|
||||
Each module's API doc must use the actual object name returned by `require('electron')`
|
||||
as its title (such as `BrowserWindow`, `autoUpdater`, and `session`).
|
||||
Each page must use the actual object name returned by `require('electron')`
|
||||
as the title, such as `BrowserWindow`, `autoUpdater`, and `session`.
|
||||
|
||||
Directly under the page title, add a one-line description of the module
|
||||
as a markdown quote (beginning with `>`).
|
||||
Under the page title must be a one-line description starting with `>`.
|
||||
|
||||
Using the `session` module as an example:
|
||||
Using `session` as example:
|
||||
|
||||
```markdown
|
||||
# session
|
||||
@@ -107,19 +99,14 @@ Using `autoUpdater` as an example:
|
||||
* API classes or classes that are part of modules must be listed under a
|
||||
`## Class: TheClassName` chapter.
|
||||
* One page can have multiple classes.
|
||||
* Constructors must be listed with `###`-level headings.
|
||||
* [Static Methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static)
|
||||
must be listed under a `### Static Methods` chapter.
|
||||
* [Instance Methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Prototype_methods)
|
||||
must be listed under an `### Instance Methods` chapter.
|
||||
* All methods that have a return value must start their description with
|
||||
"Returns `[TYPE]` - [Return description]"
|
||||
* If the method returns an `Object`, its structure can be specified using a colon
|
||||
followed by a newline then an unordered list of properties in the same style as
|
||||
function parameters.
|
||||
* Constructors must be listed with `###`-level titles.
|
||||
* [Static Methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static) must be listed under a `### Static Methods` chapter.
|
||||
* [Instance Methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Prototype_methods) must be listed under an `### Instance Methods` chapter.
|
||||
* All methods that have a return value must start their description with "Returns `[TYPE]` - Return description"
|
||||
* If the method returns an `Object`, its structure can be specified using a colon followed by a newline then an unordered list of properties in the same style as function parameters.
|
||||
* Instance Events must be listed under an `### Instance Events` chapter.
|
||||
* Instance Properties must be listed under an `### Instance Properties` chapter.
|
||||
* Instance Properties must start with "A [Property Type] ..."
|
||||
* Instance properties must start with "A [Property Type] ..."
|
||||
|
||||
Using the `Session` and `Cookies` classes as an example:
|
||||
|
||||
@@ -155,7 +142,7 @@ Using the `Session` and `Cookies` classes as an example:
|
||||
#### `cookies.get(filter, callback)`
|
||||
```
|
||||
|
||||
### Methods and their arguments
|
||||
### Methods
|
||||
|
||||
The methods chapter must be in the following form:
|
||||
|
||||
@@ -168,12 +155,8 @@ The methods chapter must be in the following form:
|
||||
...
|
||||
```
|
||||
|
||||
#### Heading level
|
||||
|
||||
The heading can be `###` or `####`-levels depending on whether the method
|
||||
belongs to a module or a class.
|
||||
|
||||
#### Function signature
|
||||
The title can be `###` or `####`-levels depending on whether it is a method of
|
||||
a module or a class.
|
||||
|
||||
For modules, the `objectName` is the module's name. For classes, it must be the
|
||||
name of the instance of the class, and must not be the same as the module's
|
||||
@@ -182,33 +165,23 @@ name.
|
||||
For example, the methods of the `Session` class under the `session` module must
|
||||
use `ses` as the `objectName`.
|
||||
|
||||
Optional arguments are notated by square brackets `[]` surrounding the optional
|
||||
argument as well as the comma required if this optional argument follows another
|
||||
The optional arguments are notated by square brackets `[]` surrounding the optional argument
|
||||
as well as the comma required if this optional argument follows another
|
||||
argument:
|
||||
|
||||
```markdown
|
||||
```sh
|
||||
required[, optional]
|
||||
```
|
||||
|
||||
#### Argument descriptions
|
||||
Below the method is more detailed information on each of the arguments. The type
|
||||
of argument is notated by either the common types:
|
||||
|
||||
More detailed information on each of the arguments is noted in an unordered list
|
||||
below the method. The type of argument is notated by either JavaScript primitives
|
||||
(e.g. `String`, `Promise`, or `Object`), a custom API structure like Electron's
|
||||
[`Cookie`](api/structures/cookie.md), or the wildcard `any`.
|
||||
|
||||
If the argument is of type `Array`, use `[]` shorthand with the type of value
|
||||
inside the array (for example,`any[]` or `String[]`).
|
||||
|
||||
If the argument is of type `Promise`, parametrize the type with what the promise
|
||||
resolves to (for example, `Promise<void>` or `Promise<String>`).
|
||||
|
||||
If an argument can be of multiple types, separate the types with `|`.
|
||||
|
||||
The description for `Function` type arguments should make it clear how it may be
|
||||
called and list the types of the parameters that will be passed to it.
|
||||
|
||||
#### Platform-specific functionality
|
||||
* [`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)
|
||||
* [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)
|
||||
* [`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
|
||||
* [`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
|
||||
* [`Boolean`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
|
||||
* Or a custom type like Electron's [`WebContent`](api/web-contents.md)
|
||||
|
||||
If an argument or a method is unique to certain platforms, those platforms are
|
||||
denoted using a space-delimited italicized list following the datatype. Values
|
||||
@@ -218,6 +191,12 @@ can be `macOS`, `Windows` or `Linux`.
|
||||
* `animate` Boolean (optional) _macOS_ _Windows_ - Animate the thing.
|
||||
```
|
||||
|
||||
`Array` type arguments must specify what elements the array may include in
|
||||
the description below.
|
||||
|
||||
The description for `Function` type arguments should make it clear how it may be
|
||||
called and list the types of the parameters that will be passed to it.
|
||||
|
||||
### Events
|
||||
|
||||
The events chapter must be in following form:
|
||||
@@ -232,8 +211,8 @@ Returns:
|
||||
...
|
||||
```
|
||||
|
||||
The heading can be `###` or `####`-levels depending on whether the event
|
||||
belongs to a module or a class.
|
||||
The title can be `###` or `####`-levels depending on whether it is an event of
|
||||
a module or a class.
|
||||
|
||||
The arguments of an event follow the same rules as methods.
|
||||
|
||||
@@ -247,13 +226,9 @@ The properties chapter must be in following form:
|
||||
...
|
||||
```
|
||||
|
||||
The heading can be `###` or `####`-levels depending on whether the property
|
||||
belongs to a module or a class.
|
||||
The title can be `###` or `####`-levels depending on whether it is a property of
|
||||
a module or a class.
|
||||
|
||||
## Documentation translations
|
||||
## Documentation Translations
|
||||
|
||||
See [electron/i18n](https://github.com/electron/i18n#readme)
|
||||
|
||||
[title-case]: https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case
|
||||
[sentence-case]: https://apastyle.apa.org/style-grammar-guidelines/capitalization/sentence-case
|
||||
[markdownlint]: https://github.com/DavidAnson/markdownlint
|
||||
|
||||
@@ -189,7 +189,7 @@ You can get a code signing certificate from a lot of resellers. Prices vary, so
|
||||
it may be worth your time to shop around. Popular resellers include:
|
||||
|
||||
* [digicert](https://www.digicert.com/code-signing/microsoft-authenticode.htm)
|
||||
* [Sectigo](https://sectigo.com/ssl-certificates-tls/code-signing)
|
||||
* [Comodo](https://www.comodo.com/landing/ssl-certificate/authenticode-signature/)
|
||||
* [GoDaddy](https://au.godaddy.com/web-security/code-signing-certificate)
|
||||
* Amongst others, please shop around to find one that suits your needs, Google
|
||||
is your friend 😄
|
||||
|
||||
@@ -47,18 +47,18 @@ of this theming, due to the use of the macOS 10.14 SDK.
|
||||
|
||||
## Example
|
||||
|
||||
This example demonstrates an Electron application that derives its theme colors from the
|
||||
`nativeTheme`. Additionally, it provides theme toggle and reset controls using IPC channels.
|
||||
We'll start with a working application from the
|
||||
[Quick Start Guide](quick-start.md) and add functionality gradually.
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/macos-dark-mode'
|
||||
First, let's edit our interface so users can toggle between light and dark
|
||||
modes. This basic UI contains buttons to change the `nativeTheme.themeSource`
|
||||
setting and a text element indicating which `themeSource` value is selected.
|
||||
By default, Electron follows the system's dark mode preference, so we
|
||||
will hardcode the theme source as "System".
|
||||
|
||||
```
|
||||
Add the following lines to the `index.html` file:
|
||||
|
||||
### How does this work?
|
||||
|
||||
Starting with the `index.html` file:
|
||||
|
||||
```html title='index.html'
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
@@ -80,70 +80,65 @@ Starting with the `index.html` file:
|
||||
</html>
|
||||
```
|
||||
|
||||
And the `style.css` file:
|
||||
Next, add [event listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
|
||||
that listen for `click` events on the toggle buttons. Because the `nativeTheme`
|
||||
module only exposed in the Main process, you need to set up each listener's
|
||||
callback to use IPC to send messages to and handle responses from the Main
|
||||
process:
|
||||
|
||||
```css title='style.css'
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body { background: #333; color: white; }
|
||||
}
|
||||
* when the "Toggle Dark Mode" button is clicked, we send the
|
||||
`dark-mode:toggle` message (event) to tell the Main process to trigger a theme
|
||||
change, and update the "Current Theme Source" label in the UI based on the
|
||||
response from the Main process.
|
||||
* when the "Reset to System Theme" button is clicked, we send the
|
||||
`dark-mode:system` message (event) to tell the Main process to use the system
|
||||
color scheme, and update the "Current Theme Source" label to `System`.
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
body { background: #ddd; color: black; }
|
||||
}
|
||||
```
|
||||
To add listeners and handlers, add the following lines to the `renderer.js` file:
|
||||
|
||||
The example renders an HTML page with a couple elements. The `<strong id="theme-source">`
|
||||
element shows which theme is currently selected, and the two `<button>` elements are the
|
||||
controls. The CSS file uses the [`prefers-color-scheme`][prefers-color-scheme] media query
|
||||
to set the `<body>` element background and text colors.
|
||||
```javascript
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
The `preload.js` script adds a new API to the `window` object called `darkMode`. This API
|
||||
exposes two IPC channels to the renderer process, `'dark-mode:toggle'` and `'dark-mode:system'`.
|
||||
It also assigns two methods, `toggle` and `system`, which pass messages from the renderer to the
|
||||
main process.
|
||||
|
||||
```js title='preload.js'
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('darkMode', {
|
||||
toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
|
||||
system: () => ipcRenderer.invoke('dark-mode:system')
|
||||
})
|
||||
```
|
||||
|
||||
Now the renderer process can communicate with the main process securely and perform the necessary
|
||||
mutations to the `nativeTheme` object.
|
||||
|
||||
The `renderer.js` file is responsible for controlling the `<button>` functionality.
|
||||
|
||||
```js title='renderer.js'
|
||||
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
|
||||
const isDarkMode = await window.darkMode.toggle()
|
||||
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 window.darkMode.system()
|
||||
await ipcRenderer.invoke('dark-mode:system')
|
||||
document.getElementById('theme-source').innerHTML = 'System'
|
||||
})
|
||||
```
|
||||
|
||||
Using `addEventListener`, the `renderer.js` file adds `'click'` [event listeners][event-listeners]
|
||||
to each button element. Each event listener handler makes calls to the respective `window.darkMode`
|
||||
API methods.
|
||||
If you run your code at this point, you'll see that your buttons don't do
|
||||
anything just yet, and your Main process will output an error like this when
|
||||
you click on your buttons:
|
||||
`Error occurred in handler for 'dark-mode:toggle': No handler registered for 'dark-mode:toggle'`
|
||||
This is expected — we haven't actually touched any `nativeTheme` code yet.
|
||||
|
||||
Finally, the `main.js` file represents the main process and contains the actual `nativeTheme` API.
|
||||
Now that we're done wiring the IPC from the Renderer's side, the next step
|
||||
is to update the `main.js` file to handle events from the Renderer process.
|
||||
|
||||
```js
|
||||
Depending on the received event, we update the
|
||||
[`nativeTheme.themeSource`](../api/native-theme.md#nativethemethemesource)
|
||||
property to apply the desired theme on the system's native UI elements
|
||||
(e.g. context menus) and propagate the preferred color scheme to the Renderer
|
||||
process:
|
||||
|
||||
* Upon receiving `dark-mode:toggle`, we check if the dark theme is currently
|
||||
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`.
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
@@ -163,37 +158,40 @@ function createWindow () {
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `ipcMain.handle` methods are how the main process responds to the click events from the buttons
|
||||
on the HTML page.
|
||||
The final step is to add a bit of styling to enable dark mode for the web parts
|
||||
of the UI by leveraging the [`prefers-color-scheme`][prefer-color-scheme] CSS
|
||||
attribute. The value of `prefers-color-scheme` will follow your
|
||||
`nativeTheme.themeSource` setting.
|
||||
|
||||
The `'dark-mode:toggle'` IPC channel handler method checks the `shouldUseDarkColors` boolean property,
|
||||
sets the corresponding `themeSource`, and then returns the current `shouldUseDarkColors` property.
|
||||
Looking back on the renderer process event listener for this IPC channel, the return value from this
|
||||
handler is utilized to assign the correct text to the `<strong id='theme-source'>` element.
|
||||
Create a `styles.css` file and add the following lines:
|
||||
|
||||
The `'dark-mode:system'` IPC channel handler method assigns the string `'system'` to the `themeSource`
|
||||
and returns nothing. This also corresponds with the relative renderer process event listener as the
|
||||
method is awaited with no return value expected.
|
||||
```css fiddle='docs/fiddles/features/macos-dark-mode'
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body { background: #333; color: white; }
|
||||
}
|
||||
|
||||
Run the example using Electron Fiddle and then click the "Toggle Dark Mode" button; the app should
|
||||
start alternating between a light and dark background color.
|
||||
@media (prefers-color-scheme: light) {
|
||||
body { background: #ddd; color: black; }
|
||||
}
|
||||
```
|
||||
|
||||
After launching the Electron application, you can change modes or reset the
|
||||
theme to system default by clicking corresponding buttons:
|
||||
|
||||

|
||||
|
||||
@@ -201,5 +199,4 @@ Run the example using Electron Fiddle and then click the "Toggle Dark Mode" butt
|
||||
[electron-forge]: https://www.electronforge.io/
|
||||
[electron-packager]: https://github.com/electron/electron-packager
|
||||
[packager-darwindarkmode-api]: https://electron.github.io/electron-packager/master/interfaces/electronpackager.options.html#darwindarkmodesupport
|
||||
[prefers-color-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
|
||||
[event-listeners]: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
|
||||
[prefer-color-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
# DevTools Extension
|
||||
|
||||
Electron supports [Chrome DevTools extensions][devtools-extension], which can
|
||||
be used to extend the ability of Chrome's developer tools for debugging
|
||||
popular web frameworks.
|
||||
Electron supports the [Chrome DevTools Extension][devtools-extension], which can
|
||||
be used to extend the ability of devtools for debugging popular web frameworks.
|
||||
|
||||
## Loading a DevTools extension with tooling
|
||||
## How to load a DevTools Extension
|
||||
|
||||
The easiest way to load a DevTools extension is to use third-party tooling to automate the
|
||||
process for you. [electron-devtools-installer][electron-devtools-installer] is a popular
|
||||
NPM package that does just that.
|
||||
This document outlines the process for manually loading an extension.
|
||||
You may also try
|
||||
[electron-devtools-installer](https://github.com/GPMDP/electron-devtools-installer),
|
||||
a third-party tool that downloads extensions directly from the Chrome WebStore.
|
||||
|
||||
## Manually loading a DevTools extension
|
||||
To load an extension in Electron, you need to download it in Chrome browser,
|
||||
locate its filesystem path, and then load it by calling the
|
||||
`BrowserWindow.addDevToolsExtension(extension)` API.
|
||||
|
||||
If you don't want to use the tooling approach, you can also do all of the necessary
|
||||
operations by hand. To load an extension in Electron, you need to download it via Chrome,
|
||||
locate its filesystem path, and then load it into your [Session][session] by calling the
|
||||
[`ses.loadExtension`] API.
|
||||
Using the [React Developer Tools][react-devtools] as example:
|
||||
|
||||
Using the [React Developer Tools][react-devtools] as an example:
|
||||
|
||||
1. Install the extension in Google Chrome.
|
||||
1. Install it in Chrome browser.
|
||||
1. Navigate to `chrome://extensions`, and find its extension ID, which is a hash
|
||||
string like `fmkadmapgofadopljbjfkapdkoienihi`.
|
||||
1. Find out the filesystem location used by Chrome for storing extensions:
|
||||
1. Find out filesystem location used by Chrome for storing extensions:
|
||||
* on Windows it is `%LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensions`;
|
||||
* on Linux it could be:
|
||||
* `~/.config/google-chrome/Default/Extensions/`
|
||||
@@ -30,49 +27,37 @@ Using the [React Developer Tools][react-devtools] as an example:
|
||||
* `~/.config/google-chrome-canary/Default/Extensions/`
|
||||
* `~/.config/chromium/Default/Extensions/`
|
||||
* on macOS it is `~/Library/Application Support/Google/Chrome/Default/Extensions`.
|
||||
1. Pass the location of the extension to the [`ses.loadExtension`][load-extension]
|
||||
API. For React Developer Tools `v4.9.0`, it looks something like:
|
||||
1. Pass the location of the extension to `BrowserWindow.addDevToolsExtension`
|
||||
API, for the React Developer Tools, it is something like:
|
||||
|
||||
```javascript
|
||||
const { app, session } = require('electron')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
|
||||
// on macOS
|
||||
const reactDevToolsPath = path.join(
|
||||
os.homedir(),
|
||||
'/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.9.0_0'
|
||||
)
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
await session.defaultSession.loadExtension(reactDevToolsPath)
|
||||
})
|
||||
BrowserWindow.addDevToolsExtension(
|
||||
path.join(os.homedir(), '/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.3.0_0')
|
||||
)
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
**Note:** The `BrowserWindow.addDevToolsExtension` API cannot be called before the
|
||||
ready event of the app module is emitted.
|
||||
|
||||
* `loadExtension` returns a Promise with an [Extension object][extension-structure],
|
||||
which contains metadata about the extension that was loaded. This promise needs to
|
||||
resolve (e.g. with an `await` expression) before loading a page. Otherwise, the
|
||||
extension won't be guaranteed to load.
|
||||
* `loadExtension` cannot be called before the `ready` event of the `app` module
|
||||
is emitted, nor can it be called on in-memory (non-persistent) sessions.
|
||||
* `loadExtension` must be called on every boot of your app if you want the
|
||||
extension to be loaded.
|
||||
The extension will be remembered so you only need to call this API once per
|
||||
extension. 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.
|
||||
|
||||
### Removing a DevTools extension
|
||||
### How to remove a DevTools Extension
|
||||
|
||||
You can pass the extension's ID to the [`ses.removeExtension`][remove-extension] API to
|
||||
remove it from your Session. Loaded extensions are not persisted between
|
||||
app launches.
|
||||
You can pass the name of the extension to the `BrowserWindow.removeDevToolsExtension`
|
||||
API to remove it. The name of the extension is returned by
|
||||
`BrowserWindow.addDevToolsExtension` and you can get the names of all installed
|
||||
DevTools Extensions using the `BrowserWindow.getDevToolsExtensions` API.
|
||||
|
||||
## DevTools extension support
|
||||
## Supported DevTools Extensions
|
||||
|
||||
Electron only supports
|
||||
[a limited set of `chrome.*` APIs][supported-extension-apis],
|
||||
so extensions using unsupported `chrome.*` APIs under the hood may not work.
|
||||
|
||||
The following Devtools extensions have been tested to work in Electron:
|
||||
Electron only supports a limited set of `chrome.*` APIs, so some extensions
|
||||
using unsupported `chrome.*` APIs for chrome extension features may not work.
|
||||
Following Devtools Extensions are tested and guaranteed to work in Electron:
|
||||
|
||||
* [Ember Inspector](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi)
|
||||
* [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi)
|
||||
@@ -84,22 +69,14 @@ The following Devtools extensions have been tested to work in Electron:
|
||||
* [Redux DevTools Extension](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd)
|
||||
* [MobX Developer Tools](https://chrome.google.com/webstore/detail/mobx-developer-tools/pfgnfdagidkfgccljigdamigbcnndkod)
|
||||
|
||||
### What should I do if a DevTools extension is not working?
|
||||
### What should I do if a DevTools Extension is not working?
|
||||
|
||||
First, please make sure the extension is still being maintained and is compatible
|
||||
with the latest version of Google Chrome. We cannot provide additional support for
|
||||
unsupported extensions.
|
||||
First please make sure the extension is still being maintained, some extensions
|
||||
can not even work for recent versions of Chrome browser, and we are not able to
|
||||
do anything for them.
|
||||
|
||||
If the extension works on Chrome but not on Electron, file a bug in Electron's
|
||||
[issue tracker][issue-tracker] and describe which part
|
||||
of the extension is not working as expected.
|
||||
Then file a bug at Electron's issues list, and describe which part of the
|
||||
extension is not working as expected.
|
||||
|
||||
[devtools-extension]: https://developer.chrome.com/extensions/devtools
|
||||
[session]: ../api/session.md
|
||||
[react-devtools]: https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi
|
||||
[load-extension]: ../api/session.md#sesloadextensionpath-options
|
||||
[extension-structure]: ../api/structures/extension.md
|
||||
[remove-extension]: ../api/session.md#sesremoveextensionextensionid
|
||||
[electron-devtools-installer]: https://github.com/MarshallOfSound/electron-devtools-installer
|
||||
[supported-extension-apis]: ../api/extensions.md
|
||||
[issue-tracker]: https://github.com/electron/electron/issues
|
||||
|
||||
@@ -18,5 +18,4 @@
|
||||
| 9.0.0 | 2020-02-06 | 2020-05-19 | M83 | v12.14 |
|
||||
| 10.0.0 | 2020-05-21 | 2020-08-25 | M85 | v12.16 |
|
||||
| 11.0.0 | 2020-08-27 | 2020-11-17 | M87 | v12.18 |
|
||||
| 12.0.0 | 2020-11-19 | 2021-03-02 | M89 | v14.16 |
|
||||
| 13.0.0 | 2021-03-04 | 2021-05-25 | M91 | v14.x |
|
||||
| 12.0.0 | 2020-11-19 | 2021-03-02 | M89 | v14.x |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> A detailed look at our versioning policy and implementation.
|
||||
|
||||
As of version 2.0.0, Electron follows [SemVer](#semver). The following command will install the most recent stable build of Electron:
|
||||
As of version 2.0.0, Electron follows [semver](#semver). The following command will install the most recent stable build of Electron:
|
||||
|
||||
```sh
|
||||
npm install --save-dev electron
|
||||
@@ -16,7 +16,7 @@ npm install --save-dev electron@latest
|
||||
|
||||
## Version 1.x
|
||||
|
||||
Electron versions *< 2.0* did not conform to the [SemVer](https://semver.org) spec: major versions corresponded to end-user API changes, minor versions corresponded to Chromium major releases, and patch versions corresponded to new features and bug fixes. While convenient for developers merging features, it creates problems for developers of client-facing applications. The QA testing cycles of major apps like Slack, Stride, Teams, Skype, VS Code, Atom, and Desktop can be lengthy and stability is a highly desired outcome. There is a high risk in adopting new features while trying to absorb bug fixes.
|
||||
Electron versions *< 2.0* did not conform to the [semver](https://semver.org) spec: major versions corresponded to end-user API changes, minor versions corresponded to Chromium major releases, and patch versions corresponded to new features and bug fixes. While convenient for developers merging features, it creates problems for developers of client-facing applications. The QA testing cycles of major apps like Slack, Stride, Teams, Skype, VS Code, Atom, and Desktop can be lengthy and stability is a highly desired outcome. There is a high risk in adopting new features while trying to absorb bug fixes.
|
||||
|
||||
Here is an example of the 1.x strategy:
|
||||
|
||||
@@ -28,7 +28,7 @@ An app developed with `1.8.1` cannot take the `1.8.3` bug fix without either abs
|
||||
|
||||
There are several major changes from our 1.x strategy outlined below. Each change is intended to satisfy the needs and priorities of developers/maintainers and app developers.
|
||||
|
||||
1. Strict use of SemVer
|
||||
1. Strict use of semver
|
||||
2. Introduction of semver-compliant `-beta` tags
|
||||
3. Introduction of [conventional commit messages](https://conventionalcommits.org/)
|
||||
4. Well-defined stabilization branches
|
||||
@@ -36,11 +36,11 @@ There are several major changes from our 1.x strategy outlined below. Each chang
|
||||
|
||||
We will cover in detail how git branching works, how npm tagging works, what developers should expect to see, and how one can backport changes.
|
||||
|
||||
# SemVer
|
||||
# semver
|
||||
|
||||
From 2.0 onward, Electron will follow SemVer.
|
||||
From 2.0 onward, Electron will follow semver.
|
||||
|
||||
Below is a table explicitly mapping types of changes to their corresponding category of SemVer (e.g. Major, Minor, Patch).
|
||||
Below is a table explicitly mapping types of changes to their corresponding category of semver (e.g. Major, Minor, Patch).
|
||||
|
||||
| Major Version Increments | Minor Version Increments | Patch Version Increments |
|
||||
| ------------------------------- | ---------------------------------- | ----------------------------- |
|
||||
@@ -70,13 +70,13 @@ Developers want to know which releases are _safe_ to use. Even seemingly innocen
|
||||
* Use `~2.0.0` to admit only stability or security related fixes to your `2.0.0` release.
|
||||
* Use `^2.0.0` to admit non-breaking _reasonably stable_ feature work as well as security and bug fixes.
|
||||
|
||||
What’s important about the second point is that apps using `^` should still be able to expect a reasonable level of stability. To accomplish this, SemVer allows for a _pre-release identifier_ to indicate a particular version is not yet _safe_ or _stable_.
|
||||
What’s important about the second point is that apps using `^` should still be able to expect a reasonable level of stability. To accomplish this, semver allows for a _pre-release identifier_ to indicate a particular version is not yet _safe_ or _stable_.
|
||||
|
||||
Whatever you choose, you will periodically have to bump the version in your `package.json` as breaking changes are a fact of Chromium life.
|
||||
|
||||
The process is as follows:
|
||||
|
||||
1. All new major and minor releases lines begin with a beta series indicated by SemVer prerelease tags of `beta.N`, e.g. `2.0.0-beta.1`. After the first beta, subsequent beta releases must meet all of the following conditions:
|
||||
1. All new major and minor releases lines begin with a beta series indicated by semver prerelease tags of `beta.N`, e.g. `2.0.0-beta.1`. After the first beta, subsequent beta releases must meet all of the following conditions:
|
||||
1. The change is backwards API-compatible (deprecations are allowed)
|
||||
2. The risk to meeting our stability timeline must be low.
|
||||
2. If allowed changes need to be made once a release is beta, they are applied and the prerelease tag is incremented, e.g. `2.0.0-beta.2`.
|
||||
@@ -86,7 +86,7 @@ e.g. `2.0.1`.
|
||||
|
||||
Specifically, the above means:
|
||||
|
||||
1. Admitting non-breaking-API changes before Week 3 in the beta cycle is okay, even if those changes have the potential to cause moderate side-effects.
|
||||
1. Admitting non-breaking-API changes before Week 3 in the beta cycle is okay, even if those changes have the potential to cause moderate side-effects
|
||||
2. Admitting feature-flagged changes, that do not otherwise alter existing code paths, at most points in the beta cycle is okay. Users can explicitly enable those flags in their apps.
|
||||
3. Admitting features of any sort after Week 3 in the beta cycle is 👎 without a very good reason.
|
||||
|
||||
@@ -112,7 +112,7 @@ An example lifecycle in pictures:
|
||||
* 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`.
|
||||

|
||||
|
||||
A few examples of how various SemVer ranges will pick up new releases:
|
||||
A few examples of how various semver ranges will pick up new releases:
|
||||
|
||||

|
||||
|
||||
@@ -136,9 +136,9 @@ Feature flags are a common practice in Chromium, and are well-established in the
|
||||
|
||||
We seek to increase clarity at all levels of the update and releases process. Starting with `2.0.0` we will require pull requests adhere to the [Conventional Commits](https://conventionalcommits.org/) spec, which can be summarized as follows:
|
||||
|
||||
* Commits that would result in a SemVer **major** bump must start their body with `BREAKING CHANGE:`.
|
||||
* Commits that would result in a SemVer **minor** bump must start with `feat:`.
|
||||
* Commits that would result in a SemVer **patch** bump must start with `fix:`.
|
||||
* Commits that would result in a semver **major** bump must start their body with `BREAKING CHANGE:`.
|
||||
* Commits that would result in a semver **minor** bump must start with `feat:`.
|
||||
* Commits that would result in a semver **patch** bump must start with `fix:`.
|
||||
|
||||
* We allow squashing of commits, provided that the squashed message adheres to the above message format.
|
||||
* It is acceptable for some commits in a pull request to not include a semantic prefix, as long as the pull request title contains a meaningful encompassing semantic message.
|
||||
|
||||
@@ -11,19 +11,14 @@ npm install electron --save-dev
|
||||
See the [Electron versioning doc][versioning] for info on how to
|
||||
manage Electron versions in your apps.
|
||||
|
||||
## Running Electron ad-hoc
|
||||
## Global Installation
|
||||
|
||||
If you're in a pinch and would prefer to not use `npm install` in your local
|
||||
project, you can also run Electron ad-hoc using the [`npx`][npx] command runner
|
||||
bundled with `npm`:
|
||||
You can also install the `electron` command globally in your `$PATH`:
|
||||
|
||||
```sh
|
||||
npx electron .
|
||||
npm install electron -g
|
||||
```
|
||||
|
||||
The above command will run the current working directory with Electron. Note that
|
||||
any dependencies in your app will not be installed.
|
||||
|
||||
## Customization
|
||||
|
||||
If you want to change the architecture that is downloaded (e.g., `ia32` on an
|
||||
@@ -183,7 +178,6 @@ If you need to force a re-download of the asset and the SHASUM file set the
|
||||
|
||||
[npm]: https://docs.npmjs.com
|
||||
[versioning]: ./electron-versioning.md
|
||||
[npx]: https://docs.npmjs.com/cli/v7/commands/npx
|
||||
[releases]: https://github.com/electron/electron/releases
|
||||
[proxy-env-10]: https://github.com/gajus/global-agent/blob/v2.1.5/README.md#environment-variables
|
||||
[proxy-env]: https://github.com/np-maintain/global-tunnel/blob/v2.7.1/README.md#auto-config
|
||||
|
||||
@@ -1,111 +1,53 @@
|
||||
# Mac App Store Submission Guide
|
||||
|
||||
This guide provides information on:
|
||||
Since v0.34.0, Electron allows submitting packaged apps to the Mac App Store
|
||||
(MAS). This guide provides information on: how to submit your app and the
|
||||
limitations of the MAS build.
|
||||
|
||||
* How to sign Electron apps on macOS;
|
||||
* How to submit Electron apps to Mac App Store (MAS);
|
||||
* The limitations of the MAS build.
|
||||
**Note:** Submitting an app to Mac App Store requires enrolling in the [Apple Developer
|
||||
Program][developer-program], which costs money.
|
||||
|
||||
## Requirements
|
||||
## How to Submit Your App
|
||||
|
||||
To sign Electron apps, the following tools must be installed first:
|
||||
The following steps introduce a simple way to submit your app to Mac App Store.
|
||||
However, these steps do not ensure your app will be approved by Apple; you
|
||||
still need to read Apple's [Submitting Your App][submitting-your-app] guide on
|
||||
how to meet the Mac App Store requirements.
|
||||
|
||||
* Xcode 11 or above.
|
||||
* The [electron-osx-sign][electron-osx-sign] npm module.
|
||||
### Get Certificate
|
||||
|
||||
You also have to register an Apple Developer account and join the
|
||||
[Apple Developer Program][developer-program].
|
||||
To submit your app to the Mac App Store, you first must get a certificate from
|
||||
Apple. You can follow these [existing guides][nwjs-guide] on web.
|
||||
|
||||
## Sign Electron apps
|
||||
### Get Team ID
|
||||
|
||||
Electron apps can be distributed through Mac App Store or outside it. Each way
|
||||
requires different ways of signing and testing. This guide focuses on
|
||||
distribution via Mac App Store, but will also mention other methods.
|
||||
Before signing your app, you need to know the Team ID of your account. To locate
|
||||
your Team ID, Sign in to [Apple Developer Center](https://developer.apple.com/account/),
|
||||
and click Membership in the sidebar. Your Team ID appears in the Membership
|
||||
Information section under the team name.
|
||||
|
||||
The following steps describe how to get the certificates from Apple, how to sign
|
||||
Electron apps, and how to test them.
|
||||
### Sign Your App
|
||||
|
||||
### Get certificates
|
||||
After finishing the preparation work, you can package your app by following
|
||||
[Application Distribution](application-distribution.md), and then proceed to
|
||||
signing your app.
|
||||
|
||||
The simplest way to get signing certificates is to use Xcode:
|
||||
First, you have to add a `ElectronTeamID` key to your app's `Info.plist`, which
|
||||
has your Team ID as its value:
|
||||
|
||||
1. Open Xcode and open "Accounts" preferences;
|
||||
2. Sign in with your Apple account;
|
||||
3. Select a team and click "Manage Certificates";
|
||||
4. In the lower-left corner of the signing certificates sheet, click the Add
|
||||
button (+), and add following certificates:
|
||||
* "Apple Development"
|
||||
* "Apple Distribution"
|
||||
```xml
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
...
|
||||
<key>ElectronTeamID</key>
|
||||
<string>TEAM_ID</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
The "Apple Development" certificate is used to sign apps for development and
|
||||
testing, on machines that have been registered on Apple Developer website. The
|
||||
method of registration will be described in
|
||||
[Prepare provisioning profile](#prepare-provisioning-profile).
|
||||
Then, you need to prepare three entitlements files.
|
||||
|
||||
Apps signed with the "Apple Development" certificate cannot be submitted to Mac
|
||||
App Store. For that purpose, apps must be signed with the "Apple Distribution"
|
||||
certificate instead. But note that apps signed with the "Apple Distribution"
|
||||
certificate cannot run directly, they must be re-signed by Apple to be able to
|
||||
run, which will only be possible after being downloaded from the Mac App Store.
|
||||
|
||||
#### Other certificates
|
||||
|
||||
You may notice that there are also other kinds of certificates.
|
||||
|
||||
The "Developer ID Application" certificate is used to sign apps before
|
||||
distributing them outside the Mac App Store.
|
||||
|
||||
The "Developer ID Installer" and "Mac Installer Distribution" certificates are
|
||||
used to sign the Mac Installer Package instead of the app itself. Most Electron
|
||||
apps do not use Mac Installer Package so they are generally not needed.
|
||||
|
||||
The full list of certificate types can be found
|
||||
[here](https://help.apple.com/xcode/mac/current/#/dev80c6204ec).
|
||||
|
||||
Apps signed with "Apple Development" and "Apple Distribution" certificates can
|
||||
only run under [App Sandbox][app-sandboxing], so they must use the MAS build of
|
||||
Electron. However, the "Developer ID Application" certificate does not have this
|
||||
restrictions, so apps signed with it can use either the normal build or the MAS
|
||||
build of Electron.
|
||||
|
||||
#### Legacy certificate names
|
||||
|
||||
Apple has been changing the names of certificates during past years, you might
|
||||
encounter them when reading old documentations, and some utilities are still
|
||||
using one of the old names.
|
||||
|
||||
* The "Apple Distribution" certificate was also named as "3rd Party Mac
|
||||
Developer Application" and "Mac App Distribution".
|
||||
* The "Apple Development" certificate was also named as "Mac Developer" and
|
||||
"Development".
|
||||
|
||||
### Prepare provisioning profile
|
||||
|
||||
If you want to test your app on your local machine before submitting your app to
|
||||
the Mac App Store, you have to sign the app with the "Apple Development"
|
||||
certificate with the provisioning profile embedded in the app bundle.
|
||||
|
||||
To [create a provisioning profile](https://help.apple.com/developer-account/#/devf2eb157f8),
|
||||
you can follow the below steps:
|
||||
|
||||
1. Open the "Certificates, Identifiers & Profiles" page on the
|
||||
[Apple Developer](https://developer.apple.com/account) website.
|
||||
2. Add a new App ID for your app in the "Identifiers" page.
|
||||
3. Register your local machine in the "Devices" page. You can find your
|
||||
machine's "Device ID" in the "Hardware" page of the "System Information" app.
|
||||
4. Register a new Provisioning Profile in the "Profiles" page, and download it
|
||||
to `/path/to/yourapp.provisionprofile`.
|
||||
|
||||
### Enable Apple's App Sandbox
|
||||
|
||||
Apps submitted to the Mac App Store must run under Apple's
|
||||
[App Sandbox][app-sandboxing], and only the MAS build of Electron can run with
|
||||
the App Sandbox. The standard darwin build of Electron will fail to launch
|
||||
when run under App Sandbox.
|
||||
|
||||
When signing the app with `electron-osx-sign`, it will automatically add the
|
||||
necessary entitlements to your app's entitlements, but if you are using custom
|
||||
entitlements, you must ensure App Sandbox capacity is added:
|
||||
`child.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -114,14 +56,13 @@ entitlements, you must ensure App Sandbox capacity is added:
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.inherit</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
#### Extra steps without `electron-osx-sign`
|
||||
|
||||
If you are signing your app without using `electron-osx-sign`, you must ensure
|
||||
the app bundle's entitlements have at least following keys:
|
||||
`parent.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -138,11 +79,7 @@ the app bundle's entitlements have at least following keys:
|
||||
</plist>
|
||||
```
|
||||
|
||||
The `TEAM_ID` should be replaced with your Apple Developer account's Team ID,
|
||||
and the `your.bundle.id` should be replaced with the App ID of the app.
|
||||
|
||||
And the following entitlements must be added to the binaries and helpers in
|
||||
the app's bundle:
|
||||
`loginhelper.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -151,97 +88,80 @@ the app's bundle:
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.inherit</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
And the app bundle's `Info.plist` must include `ElectronTeamID` key, which has
|
||||
your Apple Developer account's Team ID as its value:
|
||||
You have to replace `TEAM_ID` with your Team ID, and replace `your.bundle.id`
|
||||
with the Bundle ID of your app.
|
||||
|
||||
```xml
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
...
|
||||
<key>ElectronTeamID</key>
|
||||
<string>TEAM_ID</string>
|
||||
</dict>
|
||||
</plist>
|
||||
And then sign your app with the following script:
|
||||
|
||||
```sh
|
||||
#!/bin/bash
|
||||
|
||||
# Name of your app.
|
||||
APP="YourApp"
|
||||
# The path of your app to sign.
|
||||
APP_PATH="/path/to/YourApp.app"
|
||||
# The path to the location you want to put the signed package.
|
||||
RESULT_PATH="~/Desktop/$APP.pkg"
|
||||
# The name of certificates you requested.
|
||||
APP_KEY="3rd Party Mac Developer Application: Company Name (APPIDENTITY)"
|
||||
INSTALLER_KEY="3rd Party Mac Developer Installer: Company Name (APPIDENTITY)"
|
||||
# The path of your plist files.
|
||||
CHILD_PLIST="/path/to/child.plist"
|
||||
PARENT_PLIST="/path/to/parent.plist"
|
||||
LOGINHELPER_PLIST="/path/to/loginhelper.plist"
|
||||
|
||||
FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks"
|
||||
|
||||
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Electron Framework"
|
||||
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libffmpeg.dylib"
|
||||
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libnode.dylib"
|
||||
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework"
|
||||
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/Contents/MacOS/$APP Helper"
|
||||
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/"
|
||||
codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/Contents/MacOS/$APP Login Helper"
|
||||
codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/"
|
||||
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$APP_PATH/Contents/MacOS/$APP"
|
||||
codesign -s "$APP_KEY" -f --entitlements "$PARENT_PLIST" "$APP_PATH"
|
||||
|
||||
productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH"
|
||||
```
|
||||
|
||||
When using `electron-osx-sign` the `ElectronTeamID` key will be added
|
||||
automatically by extracting the Team ID from the certificate's name. You may
|
||||
need to manually add this key if `electron-osx-sign` could not find the correct
|
||||
Team ID.
|
||||
If you are new to app sandboxing under macOS, you should also read through
|
||||
Apple's [Enabling App Sandbox][enable-app-sandbox] to have a basic idea, then
|
||||
add keys for the permissions needed by your app to the entitlements files.
|
||||
|
||||
### Sign apps for development
|
||||
Apart from manually signing your app, you can also choose to use the
|
||||
[electron-osx-sign][electron-osx-sign] module to do the job.
|
||||
|
||||
To sign an app that can run on your development machine, you must sign it with
|
||||
the "Apple Development" certificate and pass the provisioning profile to
|
||||
`electron-osx-sign`.
|
||||
#### Sign Native Modules
|
||||
|
||||
```bash
|
||||
electron-osx-sign YourApp.app --identity='Apple Development' --provisioning-profile=/path/to/yourapp.provisionprofile
|
||||
Native modules used in your app also need to be signed. If using
|
||||
electron-osx-sign, be sure to include the path to the built binaries in the
|
||||
argument list:
|
||||
|
||||
```sh
|
||||
electron-osx-sign YourApp.app YourApp.app/Contents/Resources/app/node_modules/nativemodule/build/release/nativemodule
|
||||
```
|
||||
|
||||
If you are signing without `electron-osx-sign`, you must place the provisioning
|
||||
profile to `YourApp.app/Contents/embedded.provisionprofile`.
|
||||
Also note that native modules may have intermediate files produced which should
|
||||
not be included (as they would also need to be signed). If you use
|
||||
[electron-packager][electron-packager] before version 8.1.0, add
|
||||
`--ignore=.+\.o$` to your build step to ignore these files. Versions 8.1.0 and
|
||||
later ignore those files by default.
|
||||
|
||||
The signed app can only run on the machines that registered by the provisioning
|
||||
profile, and this is the only way to test the signed app before submitting to
|
||||
Mac App Store.
|
||||
### Upload Your App
|
||||
|
||||
### Sign apps for submitting to the Mac App Store
|
||||
|
||||
To sign an app that will be submitted to Mac App Store, you must sign it with
|
||||
the "Apple Distribution" certificate. Note that apps signed with this
|
||||
certificate will not run anywhere, unless it is downloaded from Mac App Store.
|
||||
|
||||
```bash
|
||||
electron-osx-sign YourApp.app --identity='Apple Distribution'
|
||||
```
|
||||
|
||||
### Sign apps for distribution outside the Mac App Store
|
||||
|
||||
If you don't plan to submit the app to Mac App Store, you can sign it the
|
||||
"Developer ID Application" certificate. In this way there is no requirement on
|
||||
App Sandbox, and you should use the normal darwin build of Electron if you don't
|
||||
use App Sandbox.
|
||||
|
||||
```bash
|
||||
electron-osx-sign YourApp.app --identity='Developer ID Application' --no-gatekeeper-assess
|
||||
```
|
||||
|
||||
By passing `--no-gatekeeper-assess`, the `electron-osx-sign` will skip the macOS
|
||||
GateKeeper check as your app usually has not been notarized yet by this step.
|
||||
|
||||
<!-- TODO(zcbenz): Add a chapter about App Notarization -->
|
||||
This guide does not cover [App Notarization][app-notarization], but you might
|
||||
want to do it otherwise Apple may prevent users from using your app outside Mac
|
||||
App Store.
|
||||
|
||||
## Submit Apps to the Mac App Store
|
||||
|
||||
After signing the app with the "Apple Distribution" certificate, you can
|
||||
continue to submit it to Mac App Store.
|
||||
|
||||
However, this guide do not ensure your app will be approved by Apple; you
|
||||
still need to read Apple's [Submitting Your App][submitting-your-app] guide on
|
||||
how to meet the Mac App Store requirements.
|
||||
|
||||
### Upload
|
||||
|
||||
The Application Loader should be used to upload the signed app to iTunes
|
||||
After signing your app, you can use Application Loader to upload it to iTunes
|
||||
Connect for processing, making sure you have [created a record][create-record]
|
||||
before uploading.
|
||||
|
||||
If you are seeing errors like private APIs uses, you should check if the app is
|
||||
using the MAS build of Electron.
|
||||
### Submit Your App for Review
|
||||
|
||||
### Submit for review
|
||||
|
||||
After uploading, you should [submit your app for review][submit-for-review].
|
||||
After these steps, you can [submit your app for review][submit-for-review].
|
||||
|
||||
## Limitations of MAS Build
|
||||
|
||||
@@ -261,13 +181,13 @@ Also, due to the usage of app sandboxing, the resources which can be accessed by
|
||||
the app are strictly limited; you can read [App Sandboxing][app-sandboxing] for
|
||||
more information.
|
||||
|
||||
### Additional entitlements
|
||||
### Additional Entitlements
|
||||
|
||||
Depending on which Electron APIs your app uses, you may need to add additional
|
||||
entitlements to your app's entitlements file. Otherwise, the App Sandbox may
|
||||
prevent you from using them.
|
||||
entitlements to your `parent.plist` file to be able to use these APIs from your
|
||||
app's Mac App Store build.
|
||||
|
||||
#### Network access
|
||||
#### Network Access
|
||||
|
||||
Enable outgoing network connections to allow your app to connect to a server:
|
||||
|
||||
@@ -341,12 +261,15 @@ Electron uses following cryptographic algorithms:
|
||||
* RIPEMD - [ISO/IEC 10118-3](https://webstore.ansi.org/RecordDetail.aspx?sku=ISO%2FIEC%2010118-3:2004)
|
||||
|
||||
[developer-program]: https://developer.apple.com/support/compare-memberships/
|
||||
[electron-osx-sign]: https://github.com/electron/electron-osx-sign
|
||||
[app-sandboxing]: https://developer.apple.com/app-sandboxing/
|
||||
[app-notarization]: https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution
|
||||
[submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html
|
||||
[nwjs-guide]: https://github.com/nwjs/nw.js/wiki/Mac-App-Store-%28MAS%29-Submission-Guideline#first-steps
|
||||
[enable-app-sandbox]: https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html
|
||||
[create-record]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/CreatingiTunesConnectRecord.html
|
||||
[electron-osx-sign]: https://github.com/electron-userland/electron-osx-sign
|
||||
[electron-packager]: https://github.com/electron/electron-packager
|
||||
[submit-for-review]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/SubmittingTheApp.html
|
||||
[app-sandboxing]: https://developer.apple.com/app-sandboxing/
|
||||
[export-compliance]: https://help.apple.com/app-store-connect/#/devc3f64248f
|
||||
[temporary-exception]: https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/AppSandboxTemporaryExceptionEntitlements.html
|
||||
[user-selected]: https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW6
|
||||
[network-access]: https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW9
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Configuring the macOS Dock
|
||||
# macOS Dock
|
||||
|
||||
## Overview
|
||||
|
||||
Electron has APIs to configure the app's icon in the macOS Dock. A macOS-only
|
||||
API exists to create a custom dock menu, but Electron also uses the app dock
|
||||
@@ -23,16 +25,7 @@ Starting with a working application from the
|
||||
following lines:
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/macos-dock-menu'
|
||||
const { app, BrowserWindow, Menu } = require('electron')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
const { app, Menu } = require('electron')
|
||||
|
||||
const dockMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
@@ -49,23 +42,8 @@ const dockMenu = Menu.buildFromTemplate([
|
||||
])
|
||||
|
||||
app.whenReady().then(() => {
|
||||
if (process.platform === 'darwin') {
|
||||
app.dock.setMenu(dockMenu)
|
||||
}
|
||||
}).then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
app.dock.setMenu(dockMenu)
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
After launching the Electron application, right click the application icon.
|
||||
|
||||
@@ -1,325 +0,0 @@
|
||||
# MessagePorts in Electron
|
||||
|
||||
[`MessagePort`][]s are a web feature that allow passing messages between
|
||||
different contexts. It's like `window.postMessage`, but on different channels.
|
||||
The goal of this document is to describe how Electron extends the Channel
|
||||
Messaging model, and to give some examples of how you might use MessagePorts in
|
||||
your app.
|
||||
|
||||
Here is a very brief example of what a MessagePort is and how it works:
|
||||
|
||||
```js
|
||||
// renderer.js ///////////////////////////////////////////////////////////////
|
||||
// MessagePorts are created in pairs. A connected pair of message ports is
|
||||
// called a channel.
|
||||
const channel = new MessageChannel()
|
||||
|
||||
// The only difference between port1 and port2 is in how you use them. Messages
|
||||
// sent to port1 will be received by port2 and vice-versa.
|
||||
const port1 = channel.port1
|
||||
const port2 = channel.port2
|
||||
|
||||
// It's OK to send a message on the channel before the other end has registered
|
||||
// a listener. Messages will be queued until a listener is registered.
|
||||
port2.postMessage({ answer: 42 })
|
||||
|
||||
// Here we send the other end of the channel, port1, to the main process. It's
|
||||
// also possible to send MessagePorts to other frames, or to Web Workers, etc.
|
||||
ipcRenderer.postMessage('port', null, [port1])
|
||||
```
|
||||
|
||||
```js
|
||||
// main.js ///////////////////////////////////////////////////////////////////
|
||||
// In the main process, we receive the port.
|
||||
ipcMain.on('port', (event) => {
|
||||
// When we receive a MessagePort in the main process, it becomes a
|
||||
// MessagePortMain.
|
||||
const port = event.ports[0]
|
||||
|
||||
// MessagePortMain uses the Node.js-style events API, rather than the
|
||||
// web-style events API. So .on('message', ...) instead of .onmessage = ...
|
||||
port.on('message', (event) => {
|
||||
// data is { answer: 42 }
|
||||
const data = event.data
|
||||
})
|
||||
|
||||
// MessagePortMain queues messages until the .start() method has been called.
|
||||
port.start()
|
||||
})
|
||||
```
|
||||
|
||||
The [Channel Messaging API][] documentation is a great way to learn more about
|
||||
how MessagePorts work.
|
||||
|
||||
## MessagePorts in the main process
|
||||
|
||||
In the renderer, the `MessagePort` class behaves exactly as it does on the web.
|
||||
The main process is not a web page, though—it has no Blink integration—and so
|
||||
it does not have the `MessagePort` or `MessageChannel` classes. In order to
|
||||
handle and interact with MessagePorts in the main process, Electron adds two
|
||||
new classes: [`MessagePortMain`][] and [`MessageChannelMain`][]. These behave
|
||||
similarly to the analogous classes in the renderer.
|
||||
|
||||
`MessagePort` objects can be created in either the renderer or the main
|
||||
process, and passed back and forth using the [`ipcRenderer.postMessage`][] and
|
||||
[`WebContents.postMessage`][] methods. Note that the usual IPC methods like
|
||||
`send` and `invoke` cannot be used to transfer `MessagePort`s, only the
|
||||
`postMessage` methods can transfer `MessagePort`s.
|
||||
|
||||
By passing `MessagePort`s via the main process, you can connect two pages that
|
||||
might not otherwise be able to communicate (e.g. due to same-origin
|
||||
restrictions).
|
||||
|
||||
## Extension: `close` event
|
||||
|
||||
Electron adds one feature to `MessagePort` that isn't present on the web, in
|
||||
order to make MessagePorts more useful. That is the `close` event, which is
|
||||
emitted when the other end of the channel is closed. Ports can also be
|
||||
implicitly closed by being garbage-collected.
|
||||
|
||||
In the renderer, you can listen for the `close` event either by assigning to
|
||||
`port.onclose` or by calling `port.addEventListener('close', ...)`. In the main
|
||||
process, you can listen for the `close` event by calling `port.on('close',
|
||||
...)`.
|
||||
|
||||
## Example use cases
|
||||
|
||||
### Worker process
|
||||
|
||||
In this example, your app has a worker process implemented as a hidden window.
|
||||
You want the app page to be able to communicate directly with the worker
|
||||
process, without the performance overhead of relaying via the main process.
|
||||
|
||||
```js
|
||||
// main.js ///////////////////////////////////////////////////////////////////
|
||||
const { BrowserWindow, app, ipcMain, MessageChannelMain } = require('electron')
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
// The worker process is a hidden BrowserWindow, so that it will have access
|
||||
// to a full Blink context (including e.g. <canvas>, audio, fetch(), etc.)
|
||||
const worker = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: { nodeIntegration: true }
|
||||
})
|
||||
await worker.loadFile('worker.html')
|
||||
|
||||
// The main window will send work to the worker process and receive results
|
||||
// over a MessagePort.
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: { nodeIntegration: true }
|
||||
})
|
||||
mainWindow.loadFile('app.html')
|
||||
|
||||
// We can't use ipcMain.handle() here, because the reply needs to transfer a
|
||||
// MessagePort.
|
||||
ipcMain.on('request-worker-channel', (event) => {
|
||||
// For security reasons, let's make sure only the frames we expect can
|
||||
// access the worker.
|
||||
if (event.senderFrame === mainWindow.webContents.mainFrame) {
|
||||
// Create a new channel ...
|
||||
const { port1, port2 } = new MessageChannelMain()
|
||||
// ... send one end to the worker ...
|
||||
worker.webContents.postMessage('new-client', null, [port1])
|
||||
// ... and the other end to the main window.
|
||||
event.senderFrame.postMessage('provide-worker-channel', null, [port2])
|
||||
// Now the main window and the worker can communicate with each other
|
||||
// without going through the main process!
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- worker.html ------------------------------------------------------------>
|
||||
<script>
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
function doWork(input) {
|
||||
// Something cpu-intensive.
|
||||
return input * 2
|
||||
}
|
||||
|
||||
// We might get multiple clients, for instance if there are multiple windows,
|
||||
// or if the main window reloads.
|
||||
ipcRenderer.on('new-client', (event) => {
|
||||
const [ port ] = event.ports
|
||||
port.onmessage = (event) => {
|
||||
// The event data can be any serializable object (and the event could even
|
||||
// carry other MessagePorts with it!)
|
||||
const result = doWork(event.data)
|
||||
port.postMessage(result)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- app.html --------------------------------------------------------------->
|
||||
<script>
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
// We request that the main process sends us a channel we can use to
|
||||
// communicate with the worker.
|
||||
ipcRenderer.send('request-worker-channel')
|
||||
|
||||
ipcRenderer.once('provide-worker-channel', (event) => {
|
||||
// Once we receive the reply, we can take the port...
|
||||
const [ port ] = event.ports
|
||||
// ... register a handler to receive results ...
|
||||
port.onmessage = (event) => {
|
||||
console.log('received result:', event.data)
|
||||
}
|
||||
// ... and start sending it work!
|
||||
port.postMessage(21)
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
### Reply streams
|
||||
|
||||
Electron's built-in IPC methods only support two modes: fire-and-forget
|
||||
(e.g. `send`), or request-response (e.g. `invoke`). Using MessageChannels, you
|
||||
can implement a "response stream", where a single request responds with a
|
||||
stream of data.
|
||||
|
||||
```js
|
||||
// renderer.js ///////////////////////////////////////////////////////////////
|
||||
|
||||
function makeStreamingRequest (element, callback) {
|
||||
// MessageChannels are lightweight--it's cheap to create a new one for each
|
||||
// request.
|
||||
const { port1, port2 } = new MessageChannel()
|
||||
|
||||
// We send one end of the port to the main process ...
|
||||
ipcRenderer.postMessage(
|
||||
'give-me-a-stream',
|
||||
{ element, count: 10 },
|
||||
[port2]
|
||||
)
|
||||
|
||||
// ... and we hang on to the other end. The main process will send messages
|
||||
// to its end of the port, and close it when it's finished.
|
||||
port1.onmessage = (event) => {
|
||||
callback(event.data)
|
||||
}
|
||||
port1.onclose = () => {
|
||||
console.log('stream ended')
|
||||
}
|
||||
}
|
||||
|
||||
makeStreamingRequest(42, (data) => {
|
||||
console.log('got response data:', event.data)
|
||||
})
|
||||
// We will see "got response data: 42" 10 times.
|
||||
```
|
||||
|
||||
```js
|
||||
// main.js ///////////////////////////////////////////////////////////////////
|
||||
|
||||
ipcMain.on('give-me-a-stream', (event, msg) => {
|
||||
// The renderer has sent us a MessagePort that it wants us to send our
|
||||
// response over.
|
||||
const [replyPort] = event.ports
|
||||
|
||||
// Here we send the messages synchronously, but we could just as easily store
|
||||
// the port somewhere and send messages asynchronously.
|
||||
for (let i = 0; i < msg.count; i++) {
|
||||
replyPort.postMessage(msg.element)
|
||||
}
|
||||
|
||||
// We close the port when we're done to indicate to the other end that we
|
||||
// won't be sending any more messages. This isn't strictly necessary--if we
|
||||
// didn't explicitly close the port, it would eventually be garbage
|
||||
// collected, which would also trigger the 'close' event in the renderer.
|
||||
replyPort.close()
|
||||
})
|
||||
```
|
||||
|
||||
### Communicating directly between the main process and the main world of a context-isolated page
|
||||
|
||||
When [context isolation][] is enabled, IPC messages from the main process to
|
||||
the renderer are delivered to the isolated world, rather than to the main
|
||||
world. Sometimes you want to deliver messages to the main world directly,
|
||||
without having to step through the isolated world.
|
||||
|
||||
```js
|
||||
// main.js ///////////////////////////////////////////////////////////////////
|
||||
const { BrowserWindow, app, MessageChannelMain } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
// Create a BrowserWindow with contextIsolation enabled.
|
||||
const bw = new BrowserWindow({
|
||||
webPreferences: {
|
||||
contextIsolation: true,
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
bw.loadURL('index.html')
|
||||
|
||||
// We'll be sending one end of this channel to the main world of the
|
||||
// context-isolated page.
|
||||
const { port1, port2 } = new MessageChannelMain()
|
||||
|
||||
// It's OK to send a message on the channel before the other end has
|
||||
// registered a listener. Messages will be queued until a listener is
|
||||
// registered.
|
||||
port2.postMessage({ test: 21 })
|
||||
|
||||
// We can also receive messages from the main world of the renderer.
|
||||
port2.on('message', (event) => {
|
||||
console.log('from renderer main world:', event.data)
|
||||
})
|
||||
port2.start()
|
||||
|
||||
// The preload script will receive this IPC message and transfer the port
|
||||
// over to the main world.
|
||||
bw.webContents.postMessage('main-world-port', null, [port1])
|
||||
})
|
||||
```
|
||||
|
||||
```js
|
||||
// preload.js ////////////////////////////////////////////////////////////////
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
// We need to wait until the main world is ready to receive the message before
|
||||
// sending the port. We create this promise in the preload so it's guaranteed
|
||||
// to register the onload listener before the load event is fired.
|
||||
const windowLoaded = new Promise(resolve => {
|
||||
window.onload = resolve
|
||||
})
|
||||
|
||||
ipcRenderer.on('main-world-port', async (event) => {
|
||||
await windowLoaded
|
||||
// We use regular window.postMessage to transfer the port from the isolated
|
||||
// world to the main world.
|
||||
window.postMessage('main-world-port', '*', event.ports)
|
||||
})
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- index.html ------------------------------------------------------------->
|
||||
<script>
|
||||
window.onmessage = (event) => {
|
||||
// event.source === window means the message is coming from the preload
|
||||
// script, as opposed to from an <iframe> or other source.
|
||||
if (event.source === window && event.data === 'main-world-port') {
|
||||
const [ port ] = event.ports
|
||||
// Once we have the port, we can communicate directly with the main
|
||||
// process.
|
||||
port.onmessage = (event) => {
|
||||
console.log('from main process:', event.data)
|
||||
port.postMessage(event.data * 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
[context isolation]: context-isolation.md
|
||||
[`ipcRenderer.postMessage`]: ../api/ipc-renderer.md#ipcrendererpostmessagechannel-message-transfer
|
||||
[`WebContents.postMessage`]: ../api/web-contents.md#contentspostmessagechannel-message-transfer
|
||||
[`MessagePortMain`]: ../api/message-port-main.md
|
||||
[`MessageChannelMain`]: ../api/message-channel-main.md
|
||||
[`MessagePort`]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort
|
||||
[Channel Messaging API]: https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API
|
||||
@@ -14,46 +14,30 @@ API in response to the `ondragstart` event.
|
||||
|
||||
## Example
|
||||
|
||||
An example demonstrating how you can create a file on the fly to be dragged out of the window.
|
||||
|
||||
### Preload.js
|
||||
|
||||
In `preload.js` use the [`contextBridge`] to inject a method `window.electron.startDrag(...)` that will send an IPC message to the main process.
|
||||
|
||||
```js
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
startDrag: (fileName) => {
|
||||
ipcRenderer.send('ondragstart', path.join(process.cwd(), fileName))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Index.html
|
||||
|
||||
Add a draggable element to `index.html`, and reference your renderer script:
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), add the following lines to the
|
||||
`index.html` file:
|
||||
|
||||
```html
|
||||
<div style="border:2px solid black;border-radius:3px;padding:5px;display:inline-block" draggable="true" id="drag">Drag me</div>
|
||||
<a href="#" id="drag">Drag me</a>
|
||||
<script src="renderer.js"></script>
|
||||
```
|
||||
|
||||
### Renderer.js
|
||||
|
||||
In `renderer.js` set up the renderer process to handle drag events by calling the method you added via the [`contextBridge`] above.
|
||||
and add the following lines to the `renderer.js` file:
|
||||
|
||||
```javascript
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
document.getElementById('drag').ondragstart = (event) => {
|
||||
event.preventDefault()
|
||||
window.electron.startDrag('drag-and-drop.md')
|
||||
ipcRenderer.send('ondragstart', '/absolute/path/to/the/item')
|
||||
}
|
||||
```
|
||||
|
||||
### Main.js
|
||||
The code above instructs the Renderer process to handle the `ondragstart` event
|
||||
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
|
||||
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 fiddle='docs/fiddles/features/drag-and-drop'
|
||||
@@ -68,9 +52,7 @@ ipcMain.on('ondragstart', (event, filePath) => {
|
||||
```
|
||||
|
||||
After launching the Electron application, try dragging and dropping
|
||||
the item from the BrowserWindow onto your desktop. In this guide,
|
||||
the item from the BroswerWindow onto your desktop. In this guide,
|
||||
the item is a Markdown file located in the root of the project:
|
||||
|
||||

|
||||
|
||||
[`contextBridge`]: ../api/context-bridge.md
|
||||
|
||||
@@ -32,7 +32,6 @@ From a development perspective, an Electron application is essentially a Node.js
|
||||
my-electron-app/
|
||||
├── package.json
|
||||
├── main.js
|
||||
├── preload.js
|
||||
└── index.html
|
||||
```
|
||||
|
||||
@@ -56,49 +55,45 @@ The main script may look as follows:
|
||||
|
||||
```javascript fiddle='docs/fiddles/quick-start'
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
##### What is going on above?
|
||||
|
||||
1. Line 1: First, you import the `app` and `BrowserWindow` modules of the `electron` package to be able to manage your application's lifecycle events, as well as create and control browser windows.
|
||||
2. Line 2: Second, you import the `path` package which provides utility functions for file paths.
|
||||
3. Line 4: After that, you define a function that creates a [new browser window](../api/browser-window.md#new-browserwindowoptions) with a preload script, loads `index.html` file into this window (line 13, we will discuss the file later).
|
||||
4. Line 16: You create a new browser window by invoking the `createWindow` function once the Electron application [is initialized](../api/app.md#appwhenready).
|
||||
5. Line 18: You add a new listener that creates a new browser window only if when the application has no visible windows after being activated. For example, after launching the application for the first time, or re-launching the already running application.
|
||||
6. Line 25: You add a new listener that tries to quit the application when it no longer has any open windows. This listener is a no-op on macOS due to the operating system's [window management behavior](https://support.apple.com/en-ca/guide/mac-help/mchlp2469/mac).
|
||||
2. Line 3: After that, you define a function that creates a [new browser window](../api/browser-window.md#new-browserwindowoptions) with node integration enabled, loads `index.html` file into this window (line 12, we will discuss the file later).
|
||||
3. Line 15: You create a new browser window by invoking the `createWindow` function once the Electron application [is initialized](../api/app.md#appwhenready).
|
||||
4. Line 17: You add a new listener that tries to quit the application when it no longer has any open windows. This listener is a no-op on macOS due to the operating system's [window management behavior](https://support.apple.com/en-ca/guide/mac-help/mchlp2469/mac).
|
||||
5. Line 23: You add a new listener that creates a new browser window only if when the application has no visible windows after being activated. For example, after launching the application for the first time, or re-launching the already running application.
|
||||
|
||||
#### Create a web page
|
||||
|
||||
This is the web page you want to display once the application is initialized. This web page represents the Renderer process. You can create multiple browser windows, where each window uses its own independent Renderer. You can optionally grant access to additional Node.js APIs by exposing them from your preload script.
|
||||
This is the web page you want to display once the application is initialized. This web page represents the Renderer process. You can create multiple browser windows, where each window uses its own independent Renderer. Each window can optionally be granted with full access to Node.js API through the `nodeIntegration` preference.
|
||||
|
||||
The `index.html` page looks as follows:
|
||||
|
||||
@@ -113,38 +108,14 @@ The `index.html` page looks as follows:
|
||||
<body style="background: white;">
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using Node.js <span id="node-version"></span>,
|
||||
Chromium <span id="chrome-version"></span>,
|
||||
and Electron <span id="electron-version"></span>.
|
||||
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>
|
||||
```
|
||||
|
||||
#### Define a preload script
|
||||
|
||||
Your preload script (in our case, the `preload.js` file) acts as a bridge between Node.js and your web page. It allows you to expose specific APIs and behaviors to your web page rather than insecurely exposing the entire Node.js API. In this example we will use the preload script to read version information from the `process` object and update the web page with that info.
|
||||
|
||||
```javascript fiddle='docs/fiddles/quick-start'
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const replaceText = (selector, text) => {
|
||||
const element = document.getElementById(selector)
|
||||
if (element) element.innerText = text
|
||||
}
|
||||
|
||||
for (const type of ['chrome', 'node', 'electron']) {
|
||||
replaceText(`${type}-version`, process.versions[type])
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
##### What's going on above?
|
||||
|
||||
1. On line 1: First you define an event listener that tells you when the web page has loaded
|
||||
2. On line 2: Second you define a utility function used to set the text of the placeholders in the `index.html`
|
||||
3. On line 7: Next you loop through the list of components whose version you want to display
|
||||
4. On line 8: Finally, you call `replaceText` to look up the version placeholders in `index.html` and set their text value to the values from `process.versions`
|
||||
|
||||
#### Modify your package.json file
|
||||
|
||||
Your Electron application uses the `package.json` file as the main entry point (as any other Node.js application). The main script of your application is `main.js`, so modify the `package.json` file accordingly:
|
||||
@@ -196,8 +167,7 @@ The simplest and the fastest way to distribute your newly created app is using
|
||||
1. Import Electron Forge to your app folder:
|
||||
|
||||
```sh
|
||||
npm install --save-dev @electron-forge/cli
|
||||
npx electron-forge import
|
||||
npx @electron-forge/cli import
|
||||
|
||||
✔ Checking your system
|
||||
✔ Initializing Git Repository
|
||||
@@ -312,7 +282,7 @@ ipcRenderer.invoke('perform-action', ...args)
|
||||
|
||||
##### Node.js API
|
||||
|
||||
> NOTE: To access the Node.js API from the Renderer process, you need to set the `nodeIntegration` preference to `true` and the `contextIsolation` preference to `false`. Please note that access to the Node.js API in any renderer that loads remote content is not recommended for [security reasons](../tutorial/security.md#2-do-not-enable-nodejs-integration-for-remote-content).
|
||||
> NOTE: To access the Node.js API from the Renderer process, you need to set the `nodeIntegration` preference to `true`.
|
||||
|
||||
Electron exposes full access to Node.js API and its modules both in the Main and the Renderer processes. For example, you can read all the files from the root directory:
|
||||
|
||||
|
||||
@@ -83,22 +83,6 @@ following code snippet to your menu template:
|
||||
}
|
||||
```
|
||||
|
||||
Make sure the application menu is added after the [`'ready'`](../api/app.md#event-ready)
|
||||
event and not before, or the menu item will be disabled:
|
||||
|
||||
```javascript
|
||||
const { app, Menu } = require('electron')
|
||||
|
||||
const template = [
|
||||
// Menu template here
|
||||
]
|
||||
const menu = Menu.buildFromTemplate(template)
|
||||
|
||||
app.whenReady().then(() => {
|
||||
Menu.setApplicationMenu(menu)
|
||||
})
|
||||
```
|
||||
|
||||
![macOS Recent Documents menu item][menu-item-image]
|
||||
|
||||
When a file is requested from the recent documents menu, the `open-file` event
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
# REPL
|
||||
|
||||
[Read-Eval-Print-Loop](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) (REPL)
|
||||
is a simple, interactive computer programming environment that takes single user
|
||||
inputs (i.e. single expressions), evaluates them, and returns the result to the user.
|
||||
Read-Eval-Print-Loop (REPL) is a simple, interactive computer programming
|
||||
environment that takes single user inputs (i.e. single expressions), evaluates
|
||||
them, and returns the result to the user.
|
||||
|
||||
## Main process
|
||||
The `repl` module provides a REPL implementation that can be accessed using:
|
||||
|
||||
Electron exposes the [Node.js `repl` module](https://nodejs.org/dist/latest/docs/api/repl.html)
|
||||
through the `--interactive` CLI flag. Assuming you have `electron` installed as a local project
|
||||
dependency, you should be able to access the REPL with the following command:
|
||||
* Assuming you have `electron` or `electron-prebuilt` installed as a local
|
||||
project dependency:
|
||||
|
||||
```sh
|
||||
./node_modules/.bin/electron --interactive
|
||||
```
|
||||
|
||||
**Note:** `electron --interactive` is not available on Windows
|
||||
(see [electron/electron#5776](https://github.com/electron/electron/pull/5776) for more details).
|
||||
* Assuming you have `electron` or `electron-prebuilt` installed globally:
|
||||
|
||||
## Renderer process
|
||||
```sh
|
||||
electron --interactive
|
||||
```
|
||||
|
||||
You can use the DevTools Console tab to get a REPL for any renderer process.
|
||||
To learn more, read [the Chrome documentation](https://developer.chrome.com/docs/devtools/console/).
|
||||
This only creates a REPL for the main process. You can use the Console
|
||||
tab of the Dev Tools to get a REPL for the renderer processes.
|
||||
|
||||
**Note:** `electron --interactive` is not available on Windows.
|
||||
|
||||
More information can be found in the [Node.js REPL docs](https://nodejs.org/dist/latest/docs/api/repl.html).
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
# Process Sandboxing
|
||||
|
||||
One key security feature in Chromium is that processes can be executed within a sandbox.
|
||||
The sandbox limits the harm that malicious code can cause by limiting access to most
|
||||
system resources — sandboxed processes can only freely use CPU cycles and memory.
|
||||
In order to perform operations requiring additional privilege, sandboxed processes
|
||||
use dedicated communication channels to delegate tasks to more privileged processes.
|
||||
|
||||
In Chromium, sandboxing is applied to most processes other than the main process.
|
||||
This includes renderer processes, as well as utility processes such as the audio service,
|
||||
the GPU service and the network service.
|
||||
|
||||
See Chromium's [Sandbox design document][sandbox] for more information.
|
||||
|
||||
## Electron's sandboxing policies
|
||||
|
||||
Electron comes with a mixed sandbox environment, meaning sandboxed processes can run
|
||||
alongside privileged ones. By default, renderer processes are not sandboxed, but
|
||||
utility processes are. Note that as in Chromium, the main (browser) process is
|
||||
privileged and cannot be sandboxed.
|
||||
|
||||
Historically, this mixed sandbox approach was established because having Node.js available
|
||||
in the renderer is an extremely powerful tool for app developers. Unfortunately, this
|
||||
feature is also an equally massive security vulnerability.
|
||||
|
||||
Theoretically, unsandboxed renderers are not a problem for desktop applications that
|
||||
only display trusted code, but they make Electron less secure than Chromium for
|
||||
displaying untrusted web content. However, even purportedly trusted code may be
|
||||
dangerous — there are countless attack vectors that malicious actors can use, from
|
||||
cross-site scripting to content injection to man-in-the-middle attacks on remotely loaded
|
||||
websites, just to name a few. For this reason, we recommend enabling renderer sandboxing
|
||||
for the vast majority of cases under an abundance of caution.
|
||||
|
||||
<!--TODO: update this guide when #28466 is either solved or closed -->
|
||||
Note that there is an active discussion in the issue tracker to enable renderer sandboxing
|
||||
by default. See [#28466][issue-28466]) for details.
|
||||
|
||||
## Sandbox behaviour in Electron
|
||||
|
||||
Sandboxed processes in Electron behave _mostly_ in the same way as Chromium's do, but
|
||||
Electron has a few additional concepts to consider because it interfaces with Node.js.
|
||||
|
||||
### Renderer processes
|
||||
|
||||
When renderer processes in Electron are sandboxed, they behave in the same way as a
|
||||
regular Chrome renderer would. A sandboxed renderer won't have a Node.js
|
||||
environment initialized.
|
||||
|
||||
<!-- TODO(erickzhao): when we have a solid guide for IPC, link it here -->
|
||||
Therefore, when the sandbox is enabled, renderer processes can only perform privileged
|
||||
tasks (such as interacting with the filesystem, making changes to the system, or spawning
|
||||
subprocesses) by delegating these tasks to the main process via inter-process
|
||||
communication (IPC).
|
||||
|
||||
### Preload scripts
|
||||
|
||||
In order to allow renderer processes to communicate with the main process, preload
|
||||
scripts attached to sandboxed renderers will still have a polyfilled subset of Node.js
|
||||
APIs available. A `require` function similar to Node's `require` module is exposed,
|
||||
but can only import a subset of Electron and Node's built-in modules:
|
||||
|
||||
* `electron` (only renderer process modules)
|
||||
* [`events`](https://nodejs.org/api/events.html)
|
||||
* [`timers`](https://nodejs.org/api/timers.html)
|
||||
* [`url`](https://nodejs.org/api/url.html)
|
||||
|
||||
In addition, the preload script also polyfills certain Node.js primitives as globals:
|
||||
|
||||
* [`Buffer`](https://nodejs.org/api/Buffer.html)
|
||||
* [`process`](../api/process.md)
|
||||
* [`clearImmediate`](https://nodejs.org/api/timers.html#timers_clearimmediate_immediate)
|
||||
* [`setImmediate`](https://nodejs.org/api/timers.html#timers_setimmediate_callback_args)
|
||||
|
||||
Because the `require` function is a polyfill with limited functionality, you will not be
|
||||
able to use [CommonJS modules][commonjs] to separate your preload script into multiple
|
||||
files. If you need to split your preload code, use a bundler such as [webpack][webpack]
|
||||
or [Parcel][parcel].
|
||||
|
||||
Note that because the environment presented to the `preload` script is substantially
|
||||
more privileged than that of a sandboxed renderer, it is still possible to leak
|
||||
privileged APIs to untrusted code running in the renderer process unless
|
||||
[`contextIsolation`][contextIsolation] is enabled.
|
||||
|
||||
## Configuring the sandbox
|
||||
|
||||
### Enabling the sandbox for a single process
|
||||
|
||||
In Electron, renderer sandboxing can be enabled on a per-process basis with
|
||||
the `sandbox: true` preference in the [`BrowserWindow`][browser-window] constructor.
|
||||
|
||||
```js
|
||||
// main.js
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
sandbox: true
|
||||
}
|
||||
})
|
||||
win.loadURL('https://google.com')
|
||||
})
|
||||
```
|
||||
|
||||
### Enabling the sandbox globally
|
||||
|
||||
If you want to force sandboxing for all renderers, you can also use the
|
||||
[`app.enableSandbox`][enable-sandbox] API. Note that this API has to be called before the
|
||||
app's `ready` event.
|
||||
|
||||
```js
|
||||
// main.js
|
||||
app.enableSandbox()
|
||||
app.whenReady().then(() => {
|
||||
// no need to pass `sandbox: true` since `app.enableSandbox()` was called.
|
||||
const win = new BrowserWindow()
|
||||
win.loadURL('https://google.com')
|
||||
})
|
||||
```
|
||||
|
||||
### Disabling Chromium's sandbox (testing only)
|
||||
|
||||
You can also disable Chromium's sandbox entirely with the [`--no-sandbox`][no-sandbox]
|
||||
CLI flag, which will disable the sandbox for all processes (including utility processes).
|
||||
We highly recommend that you only use this flag for testing purposes, and **never**
|
||||
in production.
|
||||
|
||||
Note that the `sandbox: true` option will still disable the renderer's Node.js
|
||||
environment.
|
||||
|
||||
## A note on rendering untrusted content
|
||||
|
||||
Rendering untrusted content in Electron is still somewhat uncharted territory,
|
||||
though some apps are finding success (e.g. [Beaker Browser][beaker]).
|
||||
Our goal is to get as close to Chrome as we can in terms of the security of
|
||||
sandboxed content, but ultimately we will always be behind due to a few fundamental
|
||||
issues:
|
||||
|
||||
1. We do not have the dedicated resources or expertise that Chromium has to
|
||||
apply to the security of its product. We do our best to make use of what we
|
||||
have, to inherit everything we can from Chromium, and to respond quickly to
|
||||
security issues, but Electron cannot be as secure as Chromium without the
|
||||
resources that Chromium is able to dedicate.
|
||||
2. Some security features in Chrome (such as Safe Browsing and Certificate
|
||||
Transparency) require a centralized authority and dedicated servers, both of
|
||||
which run counter to the goals of the Electron project. As such, we disable
|
||||
those features in Electron, at the cost of the associated security they
|
||||
would otherwise bring.
|
||||
3. There is only one Chromium, whereas there are many thousands of apps built
|
||||
on Electron, all of which behave slightly differently. Accounting for those
|
||||
differences can yield a huge possibility space, and make it challenging to
|
||||
ensure the security of the platform in unusual use cases.
|
||||
4. We can't push security updates to users directly, so we rely on app vendors
|
||||
to upgrade the version of Electron underlying their app in order for
|
||||
security updates to reach users.
|
||||
|
||||
While we make our best effort to backport Chromium security fixes to older
|
||||
versions of Electron, we do not make a guarantee that every fix will be
|
||||
backported. Your best chance at staying secure is to be on the latest stable
|
||||
version of Electron.
|
||||
|
||||
[sandbox]: https://chromium.googlesource.com/chromium/src/+/master/docs/design/sandbox.md
|
||||
[issue-28466]: https://github.com/electron/electron/issues/28466
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[enable-sandbox]: ../api/app.md#appenablesandbox
|
||||
[no-sandbox]: ../api/command-line-switches.md#--no-sandbox
|
||||
[commonjs]: https://nodejs.org/api/modules.html#modules_modules_commonjs_modules
|
||||
[webpack]: https://webpack.js.org/
|
||||
[parcel]: https://parceljs.org/
|
||||
[context-isolation]: ./context-isolation.md
|
||||
[beaker]: https://github.com/beakerbrowser/beaker
|
||||
@@ -44,7 +44,7 @@ Chromium shared library and Node.js. Vulnerabilities affecting these components
|
||||
may impact the security of your application. By updating Electron to the latest
|
||||
version, you ensure that critical vulnerabilities (such as *nodeIntegration bypasses*)
|
||||
are already patched and cannot be exploited in your application. For more information,
|
||||
see "[Use a current version of Electron](#15-use-a-current-version-of-electron)".
|
||||
see "[Use a current version of Electron](#17-use-a-current-version-of-electron)".
|
||||
|
||||
* **Evaluate your dependencies.** While NPM provides half a million reusable packages,
|
||||
it is your responsibility to choose trusted 3rd-party libraries. If you use outdated
|
||||
@@ -99,7 +99,9 @@ You should at least follow these steps to improve the security of your applicati
|
||||
12. [Disable or limit navigation](#12-disable-or-limit-navigation)
|
||||
13. [Disable or limit creation of new windows](#13-disable-or-limit-creation-of-new-windows)
|
||||
14. [Do not use `openExternal` with untrusted content](#14-do-not-use-openexternal-with-untrusted-content)
|
||||
15. [Use a current version of Electron](#15-use-a-current-version-of-electron)
|
||||
15. [Disable the `remote` module](#15-disable-the-remote-module)
|
||||
16. [Filter the `remote` module](#16-filter-the-remote-module)
|
||||
17. [Use a current version of Electron](#17-use-a-current-version-of-electron)
|
||||
|
||||
To automate the detection of misconfigurations and insecure patterns, it is
|
||||
possible to use
|
||||
@@ -663,7 +665,134 @@ const { shell } = require('electron')
|
||||
shell.openExternal('https://example.com/index.html')
|
||||
```
|
||||
|
||||
## 15) Use a current version of Electron
|
||||
## 15) Disable the `remote` module
|
||||
|
||||
The `remote` module provides a way for the renderer processes to
|
||||
access APIs normally only available in the main process. Using it, a
|
||||
renderer can invoke methods of a main process object without explicitly sending
|
||||
inter-process messages. If your desktop application does not run untrusted
|
||||
content, this can be a useful way to have your renderer processes access and
|
||||
work with modules that are only available to the main process, such as
|
||||
GUI-related modules (dialogs, menus, etc.).
|
||||
|
||||
However, if your app can run untrusted content and even if you
|
||||
[sandbox][sandbox] your renderer processes accordingly, the `remote` module
|
||||
makes it easy for malicious code to escape the sandbox and have access to
|
||||
system resources via the higher privileges of the main process. Therefore,
|
||||
it should be disabled in such circumstances.
|
||||
|
||||
### Why?
|
||||
|
||||
`remote` uses an internal IPC channel to communicate with the main process.
|
||||
"Prototype pollution" attacks can grant malicious code access to the internal
|
||||
IPC channel, which can then be used to escape the sandbox by mimicking `remote`
|
||||
IPC messages and getting access to main process modules running with higher
|
||||
privileges.
|
||||
|
||||
Additionally, it's possible for preload scripts to accidentally leak modules to a
|
||||
sandboxed renderer. Leaking `remote` arms malicious code with a multitude
|
||||
of main process modules with which to perform an attack.
|
||||
|
||||
Disabling the `remote` module eliminates these attack vectors. Enabling
|
||||
context isolation also prevents the "prototype pollution" attacks from
|
||||
succeeding.
|
||||
|
||||
### How?
|
||||
|
||||
```js
|
||||
// Bad if the renderer can run untrusted content
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
enableRemoteModule: true
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
```js
|
||||
// Good
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
enableRemoteModule: false
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- Bad if the renderer can run untrusted content -->
|
||||
<webview enableremotemodule="true" src="page.html"></webview>
|
||||
|
||||
<!-- Good -->
|
||||
<webview enableremotemodule="false" src="page.html"></webview>
|
||||
```
|
||||
|
||||
> **Note:** The default value of `enableRemoteModule` is `false` starting
|
||||
> from Electron 10. For prior versions, you need to explicitly disable
|
||||
> the `remote` module by the means above.
|
||||
|
||||
## 16) Filter the `remote` module
|
||||
|
||||
If you cannot disable the `remote` module, you should filter the globals,
|
||||
Node, and Electron modules (so-called built-ins) accessible via `remote`
|
||||
that your application does not require. This can be done by blocking
|
||||
certain modules entirely and by replacing others with proxies that
|
||||
expose only the functionality that your app needs.
|
||||
|
||||
### Why?
|
||||
|
||||
Due to the system access privileges of the main process, functionality
|
||||
provided by the main process modules may be dangerous in the hands of
|
||||
malicious code running in a compromised renderer process. By limiting
|
||||
the set of accessible modules to the minimum that your app needs and
|
||||
filtering out the others, you reduce the toolset that malicious code
|
||||
can use to attack the system.
|
||||
|
||||
Note that the safest option is to
|
||||
[fully disable the remote module](#15-disable-the-remote-module). If
|
||||
you choose to filter access rather than completely disable the module,
|
||||
you must be very careful to ensure that no escalation of privilege is
|
||||
possible through the modules you allow past the filter.
|
||||
|
||||
### How?
|
||||
|
||||
```js
|
||||
const readOnlyFsProxy = require(/* ... */) // exposes only file read functionality
|
||||
|
||||
const allowedModules = new Set(['crypto'])
|
||||
const proxiedModules = new Map(['fs', readOnlyFsProxy])
|
||||
const allowedElectronModules = new Set(['shell'])
|
||||
const allowedGlobals = new Set()
|
||||
|
||||
app.on('remote-require', (event, webContents, moduleName) => {
|
||||
if (proxiedModules.has(moduleName)) {
|
||||
event.returnValue = proxiedModules.get(moduleName)
|
||||
}
|
||||
if (!allowedModules.has(moduleName)) {
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('remote-get-builtin', (event, webContents, moduleName) => {
|
||||
if (!allowedElectronModules.has(moduleName)) {
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('remote-get-global', (event, webContents, globalName) => {
|
||||
if (!allowedGlobals.has(globalName)) {
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('remote-get-current-window', (event, webContents) => {
|
||||
event.preventDefault()
|
||||
})
|
||||
|
||||
app.on('remote-get-current-web-contents', (event, webContents) => {
|
||||
event.preventDefault()
|
||||
})
|
||||
```
|
||||
|
||||
## 17) Use a current version of Electron
|
||||
|
||||
You should strive for always using the latest available version of Electron.
|
||||
Whenever a new major version is released, you should attempt to update your
|
||||
@@ -692,5 +821,5 @@ which potential security issues are not as widely known.
|
||||
[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]: ../tutorial/sandbox.md
|
||||
[sandbox]: ../api/sandbox-option.md
|
||||
[responsible-disclosure]: https://en.wikipedia.org/wiki/Responsible_disclosure
|
||||
|
||||
@@ -64,9 +64,9 @@ until the maintainers feel the maintenance burden is too high to continue doing
|
||||
|
||||
### Currently supported versions
|
||||
|
||||
* 12.x.y
|
||||
* 11.x.y
|
||||
* 10.x.y
|
||||
* 9.x.y
|
||||
|
||||
### End-of-life
|
||||
|
||||
@@ -94,9 +94,7 @@ Following platforms are supported by Electron:
|
||||
### macOS
|
||||
|
||||
Only 64bit binaries are provided for macOS, and the minimum macOS version
|
||||
supported is macOS 10.11 (El Capitan).
|
||||
|
||||
Native support for Apple Silicon (`arm64`) devices was added in Electron 11.0.0.
|
||||
supported is macOS 10.10 (Yosemite).
|
||||
|
||||
### Windows
|
||||
|
||||
@@ -104,7 +102,7 @@ Windows 7 and later are supported, older operating systems are not supported
|
||||
(and do not work).
|
||||
|
||||
Both `ia32` (`x86`) and `x64` (`amd64`) binaries are provided for Windows.
|
||||
[Native support for Windows on Arm (`arm64`) devices was added in Electron 6.0.8.](windows-arm.md).
|
||||
[Electron 6.0.8 and later add native support for Windows on Arm (`arm64`) devices](windows-arm.md).
|
||||
Running apps packaged with previous versions is possible using the ia32 binary.
|
||||
|
||||
### Linux
|
||||
|
||||
@@ -86,12 +86,12 @@ const driver = new webdriver.Builder()
|
||||
// The "9515" is the port opened by chrome driver.
|
||||
.usingServer('http://localhost:9515')
|
||||
.withCapabilities({
|
||||
'goog:chromeOptions': {
|
||||
chromeOptions: {
|
||||
// Here is the path to your Electron binary.
|
||||
binary: '/Path-to-Your-App.app/Contents/MacOS/Electron'
|
||||
}
|
||||
})
|
||||
.forBrowser('chrome') // note: use .forBrowser('electron') for selenium-webdriver <= 3.6.0
|
||||
.forBrowser('electron')
|
||||
.build()
|
||||
|
||||
driver.get('http://www.google.com')
|
||||
|
||||
@@ -20,7 +20,7 @@ and only allow the capabilities you want to support.
|
||||
### WebViews
|
||||
|
||||
> Important Note:
|
||||
[we do not recommend you to use WebViews](../api/webview-tag.md#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
|
||||
|
||||
@@ -91,15 +91,9 @@ template("electron_extra_paks") {
|
||||
}
|
||||
|
||||
# New paks should be added here by default.
|
||||
sources += [
|
||||
"$root_gen_dir/content/browser/devtools/devtools_resources.pak",
|
||||
"$root_gen_dir/ui/resources/webui_generated_resources.pak",
|
||||
]
|
||||
sources +=
|
||||
[ "$root_gen_dir/content/browser/devtools/devtools_resources.pak" ]
|
||||
deps += [ "//content/browser/devtools:devtools_resources" ]
|
||||
if (enable_pdf_viewer) {
|
||||
sources += [ "$root_gen_dir/chrome/pdf_resources.pak" ]
|
||||
deps += [ "//chrome/browser/resources/pdf:pdf_resources" ]
|
||||
}
|
||||
if (enable_print_preview) {
|
||||
sources += [ "$root_gen_dir/chrome/print_preview_resources.pak" ]
|
||||
deps +=
|
||||
|
||||
@@ -83,18 +83,5 @@
|
||||
<message name="IDS_DOWNLOAD_MORE_ACTIONS"
|
||||
desc="Tooltip of a button on the downloads page that shows a menu with actions like 'Open downloads folder' or 'Clear all'">
|
||||
More actions
|
||||
</message>
|
||||
<!-- Badging -->
|
||||
<message name="IDS_SATURATED_BADGE_CONTENT" desc="The content to display when the application's badge is too large to display to indicate that the badge is more than a given maximum. This string should be as short as possible, preferably only one character beyond the content">
|
||||
<ph name="MAXIMUM_VALUE">$1<ex>99</ex></ph>+
|
||||
</message>
|
||||
<message name="IDS_BADGE_UNREAD_NOTIFICATIONS_SATURATED" desc="The accessibility text which will be read by a screen reader when the notification count is too large to display (e.g. greater than 99).">
|
||||
{MAX_UNREAD_NOTIFICATIONS, plural, =1 {More than 1 unread notification} other {More than # unread notifications}}
|
||||
</message>
|
||||
<message name="IDS_BADGE_UNREAD_NOTIFICATIONS_UNSPECIFIED" desc="The accessibility text which will be read by a screen reader when there are some unspecified number of notifications, or user attention is required">
|
||||
Unread Notifications
|
||||
</message>
|
||||
<message name="IDS_BADGE_UNREAD_NOTIFICATIONS" desc="The accessibility text which will be read by a screen reader when there are notifcatications">
|
||||
{UNREAD_NOTIFICATIONS, plural, =1 {1 Unread Notification} other {# Unread Notifications}}
|
||||
</message>
|
||||
</message>
|
||||
</grit-part>
|
||||
|
||||
@@ -29,10 +29,12 @@ auto_filenames = {
|
||||
"docs/api/incoming-message.md",
|
||||
"docs/api/ipc-main.md",
|
||||
"docs/api/ipc-renderer.md",
|
||||
"docs/api/locales.md",
|
||||
"docs/api/menu-item.md",
|
||||
"docs/api/menu.md",
|
||||
"docs/api/message-channel-main.md",
|
||||
"docs/api/message-port-main.md",
|
||||
"docs/api/modernization",
|
||||
"docs/api/native-image.md",
|
||||
"docs/api/native-theme.md",
|
||||
"docs/api/net-log.md",
|
||||
@@ -43,6 +45,7 @@ auto_filenames = {
|
||||
"docs/api/process.md",
|
||||
"docs/api/protocol.md",
|
||||
"docs/api/remote.md",
|
||||
"docs/api/sandbox-option.md",
|
||||
"docs/api/screen.md",
|
||||
"docs/api/service-workers.md",
|
||||
"docs/api/session.md",
|
||||
@@ -228,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",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user