Compare commits
331 Commits
v13.0.0-be
...
v13.6.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4067ec6263 | ||
|
|
a6f04822d9 | ||
|
|
9961c7aa77 | ||
|
|
aa9d2dbef7 | ||
|
|
39d55f0b6a | ||
|
|
b07b268fd0 | ||
|
|
daa220f84e | ||
|
|
f22fb9c25d | ||
|
|
c804d638fa | ||
|
|
2ee43f9ece | ||
|
|
33b54d7a8f | ||
|
|
574ee7d219 | ||
|
|
4aa6b8d001 | ||
|
|
2dd1034146 | ||
|
|
14c533c256 | ||
|
|
f8ba210b21 | ||
|
|
2f645042c2 | ||
|
|
be34c32e38 | ||
|
|
a7f4e03e1b | ||
|
|
b09dc5c4a0 | ||
|
|
ac1f5b159f | ||
|
|
9fe4fe6725 | ||
|
|
51e4b47177 | ||
|
|
f2c078ecb6 | ||
|
|
930dde396d | ||
|
|
42aa56a575 | ||
|
|
d91e53e57c | ||
|
|
1f1d139f0e | ||
|
|
18b685e397 | ||
|
|
9d3baaae58 | ||
|
|
23713aa10b | ||
|
|
883f692dad | ||
|
|
cef7a28136 | ||
|
|
d552fa0c07 | ||
|
|
2727847aca | ||
|
|
072158bf8c | ||
|
|
a733074c8c | ||
|
|
bc25056770 | ||
|
|
f0b37841ea | ||
|
|
1caf4e695d | ||
|
|
bba04ea788 | ||
|
|
3b3430fba6 | ||
|
|
c53ffadb8a | ||
|
|
e714d729b1 | ||
|
|
627bf64263 | ||
|
|
a7bbb47ec2 | ||
|
|
cf9ae70dbc | ||
|
|
044c980e96 | ||
|
|
9a71ca545f | ||
|
|
e64966641c | ||
|
|
3bb36a62cb | ||
|
|
e58a04ea5a | ||
|
|
5e32f51cf6 | ||
|
|
75349f58ad | ||
|
|
879b98c922 | ||
|
|
9d34c83089 | ||
|
|
8d8949ac60 | ||
|
|
acb2209668 | ||
|
|
4bd655a093 | ||
|
|
9c976b4f3d | ||
|
|
d70c5d1e6a | ||
|
|
d93629321e | ||
|
|
b505de0765 | ||
|
|
4c4d29eb73 | ||
|
|
993ecb5bdd | ||
|
|
d0ba8d1f69 | ||
|
|
d03fd85a90 | ||
|
|
2387d10956 | ||
|
|
558350e4bf | ||
|
|
4d960873a4 | ||
|
|
dfcb2afffd | ||
|
|
221fd9d6ce | ||
|
|
ecad7c2441 | ||
|
|
a9acc050ee | ||
|
|
29311b7d1d | ||
|
|
949ec0c7c9 | ||
|
|
91b1c0162e | ||
|
|
e20eab42d3 | ||
|
|
fe44e01dbb | ||
|
|
bc987209f8 | ||
|
|
7c2889d93a | ||
|
|
fa46c67bd3 | ||
|
|
82679f4335 | ||
|
|
75f366f4d0 | ||
|
|
1d531f29ee | ||
|
|
f75b755f21 | ||
|
|
a2929226d2 | ||
|
|
6655694cc7 | ||
|
|
1ac4d27e22 | ||
|
|
681d02a77d | ||
|
|
14eefd58c1 | ||
|
|
2beec61a50 | ||
|
|
e1ae36210b | ||
|
|
e74eac61ae | ||
|
|
f8a5c3d8ee | ||
|
|
efd18b09ca | ||
|
|
cd062ac26e | ||
|
|
a3e47196f7 | ||
|
|
1930d972fc | ||
|
|
0c4ac78dea | ||
|
|
5771f3826a | ||
|
|
a55bc6a870 | ||
|
|
dcb311d5c9 | ||
|
|
e5935eaff9 | ||
|
|
d927f1dc02 | ||
|
|
ca1cae64d9 | ||
|
|
69df216a9c | ||
|
|
2917eb1589 | ||
|
|
ec282ff385 | ||
|
|
5d98e5e78a | ||
|
|
251e7bb227 | ||
|
|
d4881625b8 | ||
|
|
348f991563 | ||
|
|
6308fc4c4e | ||
|
|
7fb719f261 | ||
|
|
d7d9d58c8b | ||
|
|
acc861dbaf | ||
|
|
18de6be607 | ||
|
|
1ae50bbeff | ||
|
|
7d129ac5c9 | ||
|
|
2cca38c036 | ||
|
|
f616c85061 | ||
|
|
393045a7e5 | ||
|
|
4a7dd267ec | ||
|
|
f2275ec32e | ||
|
|
e70c39ed60 | ||
|
|
db12e7f08b | ||
|
|
6a1c6f8d7f | ||
|
|
7bd6479573 | ||
|
|
c2de2eaaa0 | ||
|
|
62b3a6b724 | ||
|
|
c3d8337058 | ||
|
|
b3eff8ef13 | ||
|
|
6cef0d9118 | ||
|
|
65d03deacd | ||
|
|
39e55225a0 | ||
|
|
bb83758378 | ||
|
|
2716a25fcf | ||
|
|
2745d70d25 | ||
|
|
b6ffa799c5 | ||
|
|
c9bb6cd134 | ||
|
|
ac2515dd0d | ||
|
|
49436f298b | ||
|
|
542874d13b | ||
|
|
2a8e1a6de1 | ||
|
|
f5bffae462 | ||
|
|
9f80f4aa76 | ||
|
|
736150672c | ||
|
|
7434547d97 | ||
|
|
0436a27d4f | ||
|
|
6627bebdbd | ||
|
|
4a24a28467 | ||
|
|
390ed798f0 | ||
|
|
cdd2176bb6 | ||
|
|
e57b74858f | ||
|
|
3805e3c0fc | ||
|
|
5fb34249c6 | ||
|
|
06997edc3a | ||
|
|
e2b961d73c | ||
|
|
867ea38cd0 | ||
|
|
2e8f2a2f51 | ||
|
|
4da1162ffe | ||
|
|
9d3ebb1888 | ||
|
|
0b8971dec2 | ||
|
|
c8ab43a766 | ||
|
|
64c6737bb2 | ||
|
|
30b6330189 | ||
|
|
177bdd207c | ||
|
|
77fbad0333 | ||
|
|
971ec77b96 | ||
|
|
1b0c15f742 | ||
|
|
52cddbcd92 | ||
|
|
6d0feb8b79 | ||
|
|
2e096ac6bc | ||
|
|
3afe390805 | ||
|
|
d5097dd2e6 | ||
|
|
257b214cb5 | ||
|
|
945ecdd709 | ||
|
|
cb614d15aa | ||
|
|
5fbcee074d | ||
|
|
dc14161a98 | ||
|
|
299fa3a3c4 | ||
|
|
d09e7f851b | ||
|
|
84eea6fa79 | ||
|
|
0cd80cd424 | ||
|
|
78f037f639 | ||
|
|
fc75bf0a9e | ||
|
|
ddc44e1af4 | ||
|
|
5ab2749acc | ||
|
|
642c458c31 | ||
|
|
2195890a46 | ||
|
|
3413e89572 | ||
|
|
7bf69ce4ee | ||
|
|
49f5006ef0 | ||
|
|
fea59c5601 | ||
|
|
6feed17387 | ||
|
|
ec0fa836d2 | ||
|
|
56a34d3b10 | ||
|
|
bde3d403a8 | ||
|
|
8779a3ac0f | ||
|
|
b465ee721e | ||
|
|
50b0750df3 | ||
|
|
1a3da54563 | ||
|
|
fa3767564a | ||
|
|
85db7e7077 | ||
|
|
9b1d2d5b88 | ||
|
|
e8621de3f5 | ||
|
|
9942b2ba80 | ||
|
|
2bf125f82a | ||
|
|
69493ac51e | ||
|
|
6504c4bbc8 | ||
|
|
5c1e1ee5ec | ||
|
|
f39ac0764d | ||
|
|
252805ddb4 | ||
|
|
df27597c05 | ||
|
|
fa683ef8b7 | ||
|
|
16b09a676f | ||
|
|
301108ece4 | ||
|
|
5d36cdf485 | ||
|
|
c94ab729dd | ||
|
|
b35f904e58 | ||
|
|
b143042c7f | ||
|
|
10c238c0ea | ||
|
|
ad2f34491c | ||
|
|
d6c51bc456 | ||
|
|
f313d00083 | ||
|
|
2ef55e1e9e | ||
|
|
62402870fd | ||
|
|
7b2a4c9984 | ||
|
|
7958f3efbb | ||
|
|
3e90aff6fd | ||
|
|
192fc3ee2c | ||
|
|
e0e7b14bdc | ||
|
|
4cecc87c55 | ||
|
|
46e7511af9 | ||
|
|
72733bae8a | ||
|
|
38fce95417 | ||
|
|
54de33464d | ||
|
|
6c4c66d2cd | ||
|
|
839dcbbbdb | ||
|
|
05ae55d131 | ||
|
|
d7736e5924 | ||
|
|
30921548ed | ||
|
|
9059a50f93 | ||
|
|
78569e9b91 | ||
|
|
07b8b2ffdd | ||
|
|
2d18829b43 | ||
|
|
f0a9e56741 | ||
|
|
314e627df1 | ||
|
|
b5c79632ef | ||
|
|
0dcc660794 | ||
|
|
0753e4911c | ||
|
|
ff2a0a4bd3 | ||
|
|
5860b70189 | ||
|
|
d84b7fc4d4 | ||
|
|
1873d8ec81 | ||
|
|
0c19db01d9 | ||
|
|
2156a9064f | ||
|
|
6e169089f0 | ||
|
|
6855004aa5 | ||
|
|
93d9aaa99c | ||
|
|
e4a3f064de | ||
|
|
9265390164 | ||
|
|
8e6819ae71 | ||
|
|
f95d2bdfd1 | ||
|
|
737b08d130 | ||
|
|
b44024d660 | ||
|
|
d0d6e88e5a | ||
|
|
c647007ccc | ||
|
|
134c8b7ed3 | ||
|
|
4f203eee4a | ||
|
|
bb065beaa6 | ||
|
|
8481e5c08a | ||
|
|
7276a1fd8c | ||
|
|
7d18988317 | ||
|
|
68afcd16e4 | ||
|
|
72e336445a | ||
|
|
3e658c4782 | ||
|
|
e7d3b43db0 | ||
|
|
6683606449 | ||
|
|
7bcc2a2762 | ||
|
|
c04fa30944 | ||
|
|
51213f656b | ||
|
|
aba7834a17 | ||
|
|
3651c0411f | ||
|
|
cb798f26b8 | ||
|
|
215c2d3ec7 | ||
|
|
9df6131352 | ||
|
|
4d7188fd2e | ||
|
|
c69d0eea2e | ||
|
|
1e54d19e8a | ||
|
|
a660598e4c | ||
|
|
1ec2840da0 | ||
|
|
1d3cd106d1 | ||
|
|
5c5f041731 | ||
|
|
325df5afcf | ||
|
|
e261519469 | ||
|
|
042c04f95f | ||
|
|
7a78506a7d | ||
|
|
75b4db49df | ||
|
|
0f8ac92b09 | ||
|
|
119ce7d6da | ||
|
|
daa075d020 | ||
|
|
8d6b9155fb | ||
|
|
cec2bfb9ec | ||
|
|
ff1cc3c60b | ||
|
|
b4bba38862 | ||
|
|
278ff8566c | ||
|
|
323de2fbe7 | ||
|
|
cd673a3697 | ||
|
|
0097a370e3 | ||
|
|
692c510867 | ||
|
|
e6f15c4380 | ||
|
|
cce8dda92f | ||
|
|
034f750c46 | ||
|
|
120a8acfd0 | ||
|
|
01992fd65c | ||
|
|
af6a5e6c30 | ||
|
|
caac2e8fc7 | ||
|
|
9a4a049498 | ||
|
|
68059d69a5 | ||
|
|
0f7334a77e | ||
|
|
eee8bee71b | ||
|
|
2795185d46 | ||
|
|
877f096d6b | ||
|
|
b33bb3a860 | ||
|
|
86f4126051 | ||
|
|
f895162234 | ||
|
|
05e41f89b4 | ||
|
|
d7378f953a | ||
|
|
ed0b654fee |
@@ -57,6 +57,16 @@ parameters:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
# Executors
|
||||
executors:
|
||||
linux-arm:
|
||||
resource_class: electronjs/linux-arm
|
||||
machine: true
|
||||
|
||||
linux-arm64:
|
||||
resource_class: electronjs/linux-arm64
|
||||
machine: true
|
||||
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "SLACK_WEBHOOK" Slack hook URL to send notifications.
|
||||
#
|
||||
@@ -239,7 +249,14 @@ step-maybe-cleanup-arm64-mac: &step-maybe-cleanup-arm64-mac
|
||||
killall Safari || echo "No Safari processes left running"
|
||||
rm -rf ~/Library/Application\ Support/Electron*
|
||||
rm -rf ~/Library/Application\ Support/electron*
|
||||
elif [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
XVFB=/usr/bin/Xvfb
|
||||
/sbin/start-stop-daemon --stop --exec $XVFB || echo "Xvfb not running"
|
||||
pkill electron || echo "electron not running"
|
||||
rm -rf ~/.config/Electron*
|
||||
rm -rf ~/.config/electron*
|
||||
fi
|
||||
|
||||
when: always
|
||||
|
||||
step-checkout-electron: &step-checkout-electron
|
||||
@@ -278,7 +295,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="Electron Bot" GIT_COMMITTER_EMAIL="electron@github.com" git commit -m "update patches" --author="Electron Bot <electron@github.com>"
|
||||
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>"
|
||||
# Export it
|
||||
mkdir -p ../../patches
|
||||
git format-patch -1 --stdout --keep-subject --no-stat --full-index > ../../patches/update-patches.patch
|
||||
@@ -325,6 +342,7 @@ 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 })"
|
||||
export GOMA_FALLBACK_ON_AUTH_FAILURE=true
|
||||
third_party/goma/goma_ctl.py ensure_start
|
||||
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
|
||||
@@ -505,6 +523,7 @@ step-gn-check: &step-gn-check
|
||||
gn check out/Default //electron/shell/common/api:mojo
|
||||
# Check the hunspell filenames
|
||||
node electron/script/gen-hunspell-filenames.js --check
|
||||
node electron/script/gen-libc++-filenames.js --check
|
||||
|
||||
step-electron-build: &step-electron-build
|
||||
run:
|
||||
@@ -530,6 +549,7 @@ step-electron-build: &step-electron-build
|
||||
ninja -C out/Default electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/Default tools/v8_context_snapshot -j $NUMBER_OF_NINJA_PROCESSES
|
||||
gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
|
||||
(cd out/Default; zip mksnapshot.zip mksnapshot_args clang_x64_v8_arm64/gen/v8/embedded.S)
|
||||
rm -rf out/Default/clang_x64_v8_arm64/gen
|
||||
rm -rf out/Default/clang_x64_v8_arm64/obj
|
||||
rm -rf out/Default/clang_x64/obj
|
||||
@@ -687,6 +707,11 @@ step-persist-data-for-tests: &step-persist-data-for-tests
|
||||
- src/third_party/electron_node
|
||||
- src/third_party/nan
|
||||
- src/cross-arch-snapshots
|
||||
- src/third_party/llvm-build
|
||||
- src/build/linux
|
||||
- src/buildtools/third_party/libc++
|
||||
- src/buildtools/third_party/libc++abi
|
||||
- src/out/Default/obj/buildtools/third_party
|
||||
|
||||
step-electron-dist-unzip: &step-electron-dist-unzip
|
||||
run:
|
||||
@@ -756,7 +781,7 @@ step-verify-mksnapshot: &step-verify-mksnapshot
|
||||
command: |
|
||||
if [ "$IS_ASAN" != "1" ]; then
|
||||
cd src
|
||||
if [ "$TARGET_ARCH" == "arm64" ] &&[ "`uname`" == "Darwin" ]; then
|
||||
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --snapshot-files-dir $PWD/cross-arch-snapshots
|
||||
else
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default
|
||||
@@ -837,6 +862,17 @@ step-hunspell-store: &step-hunspell-store
|
||||
path: src/out/Default/hunspell_dictionaries.zip
|
||||
destination: hunspell_dictionaries.zip
|
||||
|
||||
step-maybe-generate-libcxx: &step-maybe-generate-libcxx
|
||||
run:
|
||||
name: maybe generate libcxx
|
||||
command: |
|
||||
cd src
|
||||
if [ "`uname`" == "Linux" ]; then
|
||||
ninja -C out/Default electron:libcxx_headers_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/Default electron:libcxxabi_headers_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/Default electron:libcxx_objects_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
fi
|
||||
|
||||
step-maybe-generate-breakpad-symbols: &step-maybe-generate-breakpad-symbols
|
||||
run:
|
||||
name: Generate breakpad symbols
|
||||
@@ -890,28 +926,6 @@ step-maybe-cross-arch-snapshot-store: &step-maybe-cross-arch-snapshot-store
|
||||
path: src/cross-arch-snapshots
|
||||
destination: cross-arch-snapshots
|
||||
|
||||
step-maybe-trigger-arm-test: &step-maybe-trigger-arm-test
|
||||
run:
|
||||
name: Trigger an arm test on VSTS if applicable
|
||||
command: |
|
||||
cd src
|
||||
# Only run for non-fork prs
|
||||
if [ "$TRIGGER_ARM_TEST" == "true" ] && [ -z "$CIRCLE_PR_NUMBER" ]; then
|
||||
#Trigger VSTS job, passing along CircleCI job number and branch to build
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
if [ x"$MAS_BUILD" == x"true" ]; then
|
||||
export DEVOPS_BUILD="electron-mas-arm64-testing"
|
||||
else
|
||||
export DEVOPS_BUILD="electron-osx-arm64-testing"
|
||||
fi
|
||||
echo "Triggering $DEVOPS_BUILD build on Azure DevOps"
|
||||
node electron/script/release/ci-release-build.js --job=$DEVOPS_BUILD --ci=DevOps --armTest --circleBuildNum=$CIRCLE_BUILD_NUM $CIRCLE_BRANCH
|
||||
else
|
||||
echo "Triggering electron-$TARGET_ARCH-testing build on VSTS"
|
||||
node electron/script/release/ci-release-build.js --job=electron-$TARGET_ARCH-testing --ci=VSTS --armTest --circleBuildNum=$CIRCLE_BUILD_NUM $CIRCLE_BRANCH
|
||||
fi
|
||||
fi
|
||||
|
||||
step-maybe-generate-typescript-defs: &step-maybe-generate-typescript-defs
|
||||
run:
|
||||
name: Generate type declarations
|
||||
@@ -1326,7 +1340,7 @@ steps-tests: &steps-tests
|
||||
(cd electron && node script/yarn test --runners=main --trace-uncaught --enable-logging --files $(circleci tests glob spec-main/*-spec.ts | circleci tests split)) 2>&1 | $ASAN_SYMBOLIZE
|
||||
(cd electron && node script/yarn test --runners=remote --trace-uncaught --enable-logging --files $(circleci tests glob spec/*-spec.js | circleci tests split)) 2>&1 | $ASAN_SYMBOLIZE
|
||||
else
|
||||
if [ "$TARGET_ARCH" == "arm64" ] &&[ "`uname`" == "Darwin" ]; then
|
||||
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
export ELECTRON_SKIP_NATIVE_MODULE_TESTS=true
|
||||
(cd electron && node script/yarn test --runners=main --trace-uncaught --enable-logging)
|
||||
(cd electron && node script/yarn test --runners=remote --trace-uncaught --enable-logging)
|
||||
@@ -1617,9 +1631,6 @@ commands:
|
||||
steps:
|
||||
- *step-save-out-cache
|
||||
|
||||
# Trigger tests on arm hardware if needed
|
||||
- *step-maybe-trigger-arm-test
|
||||
|
||||
- *step-maybe-notify-slack-failure
|
||||
|
||||
electron-publish:
|
||||
@@ -1687,6 +1698,9 @@ commands:
|
||||
- *step-hunspell-build
|
||||
- *step-hunspell-store
|
||||
|
||||
# libcxx
|
||||
- *step-maybe-generate-libcxx
|
||||
|
||||
# typescript defs
|
||||
- *step-maybe-generate-typescript-defs
|
||||
|
||||
@@ -1960,7 +1974,7 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
steps:
|
||||
- electron-build:
|
||||
persist: false
|
||||
persist: true
|
||||
checkout: true
|
||||
use-out-cache: false
|
||||
|
||||
@@ -2019,7 +2033,7 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
steps:
|
||||
- electron-build:
|
||||
persist: false
|
||||
persist: true
|
||||
checkout: true
|
||||
use-out-cache: false
|
||||
|
||||
@@ -2416,6 +2430,24 @@ jobs:
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-verify-ffmpeg
|
||||
|
||||
linux-arm-testing-tests:
|
||||
executor: linux-arm
|
||||
environment:
|
||||
<<: *env-arm
|
||||
<<: *env-global
|
||||
<<: *env-headless-testing
|
||||
<<: *env-stack-dumping
|
||||
<<: *steps-tests
|
||||
|
||||
linux-arm64-testing-tests:
|
||||
executor: linux-arm64
|
||||
environment:
|
||||
<<: *env-arm64
|
||||
<<: *env-global
|
||||
<<: *env-headless-testing
|
||||
<<: *env-stack-dumping
|
||||
<<: *steps-tests
|
||||
|
||||
osx-testing-x64-tests:
|
||||
<<: *machine-mac-large
|
||||
environment:
|
||||
@@ -2668,8 +2700,23 @@ workflows:
|
||||
- linux-ia32-testing
|
||||
|
||||
- linux-arm-testing
|
||||
- linux-arm-testing-tests:
|
||||
filters:
|
||||
branches:
|
||||
# Do not run this on forked pull requests
|
||||
ignore: /pull\/[0-9]+/
|
||||
requires:
|
||||
- linux-arm-testing
|
||||
|
||||
- linux-arm64-testing
|
||||
- linux-arm64-testing-tests:
|
||||
filters:
|
||||
branches:
|
||||
# Do not run this on forked pull requests
|
||||
ignore: /pull\/[0-9]+/
|
||||
requires:
|
||||
- linux-arm64-testing
|
||||
|
||||
- linux-arm64-testing-gn-check:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
|
||||
58
BUILD.gn
@@ -1,6 +1,7 @@
|
||||
import("//build/config/locales.gni")
|
||||
import("//build/config/ui.gni")
|
||||
import("//build/config/win/manifest.gni")
|
||||
import("//components/os_crypt/features.gni")
|
||||
import("//components/spellcheck/spellcheck_build_features.gni")
|
||||
import("//content/public/app/mac_helpers.gni")
|
||||
import("//extensions/buildflags/buildflags.gni")
|
||||
@@ -25,6 +26,8 @@ import("electron_paks.gni")
|
||||
import("filenames.auto.gni")
|
||||
import("filenames.gni")
|
||||
import("filenames.hunspell.gni")
|
||||
import("filenames.libcxx.gni")
|
||||
import("filenames.libcxxabi.gni")
|
||||
|
||||
if (is_mac) {
|
||||
import("//build/config/mac/rules.gni")
|
||||
@@ -180,6 +183,12 @@ action("electron_js2c") {
|
||||
rebase_path(sources, root_build_dir)
|
||||
}
|
||||
|
||||
action("generate_config_gypi") {
|
||||
outputs = [ "$root_gen_dir/config.gypi" ]
|
||||
script = "script/generate-config-gypi.py"
|
||||
args = rebase_path(outputs) + [ target_cpu ]
|
||||
}
|
||||
|
||||
target_gen_default_app_js = "$target_gen_dir/js/default_app"
|
||||
|
||||
typescript_build("default_app_js") {
|
||||
@@ -290,7 +299,7 @@ templated_file("electron_version_header") {
|
||||
action("electron_fuses") {
|
||||
script = "build/fuses/build.py"
|
||||
|
||||
inputs = [ "build/fuses/fuses.json" ]
|
||||
inputs = [ "build/fuses/fuses.json5" ]
|
||||
|
||||
outputs = [
|
||||
"$target_gen_dir/fuses.h",
|
||||
@@ -329,6 +338,7 @@ source_set("electron_lib") {
|
||||
"//components/network_hints/common:mojo_bindings",
|
||||
"//components/network_hints/renderer",
|
||||
"//components/network_session_configurator/common",
|
||||
"//components/os_crypt",
|
||||
"//components/pref_registry",
|
||||
"//components/prefs",
|
||||
"//components/upload_list",
|
||||
@@ -676,6 +686,10 @@ source_set("electron_lib") {
|
||||
]
|
||||
libs += [ "uxtheme.lib" ]
|
||||
}
|
||||
|
||||
if (allow_runtime_configurable_key_storage) {
|
||||
defines += [ "ALLOW_RUNTIME_CONFIGURABLE_KEY_STORAGE" ]
|
||||
}
|
||||
}
|
||||
|
||||
electron_paks("packed_resources") {
|
||||
@@ -1292,13 +1306,18 @@ template("dist_zip") {
|
||||
"testonly",
|
||||
])
|
||||
flatten = false
|
||||
flatten_relative_to = false
|
||||
if (defined(invoker.flatten)) {
|
||||
flatten = invoker.flatten
|
||||
if (defined(invoker.flatten_relative_to)) {
|
||||
flatten_relative_to = invoker.flatten_relative_to
|
||||
}
|
||||
}
|
||||
args = rebase_path(outputs + [ _runtime_deps_file ], root_build_dir) + [
|
||||
target_cpu,
|
||||
target_os,
|
||||
"$flatten",
|
||||
"$flatten_relative_to",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1389,6 +1408,43 @@ dist_zip("hunspell_dictionaries_zip") {
|
||||
outputs = [ "$root_build_dir/hunspell_dictionaries.zip" ]
|
||||
}
|
||||
|
||||
copy("libcxx_headers") {
|
||||
sources = libcxx_headers + libcxx_licenses
|
||||
outputs = [ "$target_gen_dir/electron_libcxx_include/{{source_root_relative_dir}}/{{source_file_part}}" ]
|
||||
}
|
||||
|
||||
dist_zip("libcxx_headers_zip") {
|
||||
data_deps = [ ":libcxx_headers" ]
|
||||
flatten = true
|
||||
flatten_relative_to = rebase_path(
|
||||
"$target_gen_dir/electron_libcxx_include/buildtools/third_party/libc++/trunk",
|
||||
"$root_out_dir")
|
||||
|
||||
outputs = [ "$root_build_dir/libcxx_headers.zip" ]
|
||||
}
|
||||
|
||||
copy("libcxxabi_headers") {
|
||||
sources = libcxxabi_headers + libcxxabi_licenses
|
||||
outputs = [ "$target_gen_dir/electron_libcxxabi_include/{{source_root_relative_dir}}/{{source_file_part}}" ]
|
||||
}
|
||||
|
||||
dist_zip("libcxxabi_headers_zip") {
|
||||
data_deps = [ ":libcxxabi_headers" ]
|
||||
flatten = true
|
||||
flatten_relative_to = rebase_path(
|
||||
"$target_gen_dir/electron_libcxxabi_include/buildtools/third_party/libc++abi/trunk",
|
||||
"$root_out_dir")
|
||||
|
||||
outputs = [ "$root_build_dir/libcxxabi_headers.zip" ]
|
||||
}
|
||||
|
||||
action("libcxx_objects_zip") {
|
||||
deps = [ "//buildtools/third_party/libc++" ]
|
||||
script = "build/zip_libcxx.py"
|
||||
outputs = [ "$root_build_dir/libcxx_objects.zip" ]
|
||||
args = rebase_path(outputs)
|
||||
}
|
||||
|
||||
group("electron") {
|
||||
public_deps = [ ":electron_app" ]
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ Issues are created [here](https://github.com/electron/electron/issues/new).
|
||||
|
||||
### Issue Closure
|
||||
|
||||
Bug reports will be closed if the issue has been inactive and the latest affected version no longer receives support. At the moment, Electron maintains its three latest major versions, with a new major version being released every 12 weeks. (For more information on Electron's release cadence, see [this blog post](https://electronjs.org/blog/12-week-cadence).)
|
||||
Bug reports will be closed if the issue has been inactive and the latest affected version no longer receives support. At the moment, Electron maintains its three latest major versions, with a new major version being released every 8 weeks. (For more information on Electron's release cadence, see [this blog post](https://electronjs.org/blog/8-week-cadence).)
|
||||
|
||||
_If an issue has been closed and you still feel it's relevant, feel free to ping a maintainer or add a comment!_
|
||||
|
||||
|
||||
7
DEPS
@@ -10,17 +10,18 @@ gclient_gn_args = [
|
||||
'checkout_openxr',
|
||||
'checkout_google_benchmark',
|
||||
'mac_xcode_version',
|
||||
'generate_location_tags',
|
||||
]
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'91.0.4472.33',
|
||||
'91.0.4472.164',
|
||||
'node_version':
|
||||
'v14.16.0',
|
||||
'nan_version':
|
||||
'v2.14.2',
|
||||
'squirrel.mac_version':
|
||||
'cdc0729c8bf8576bfef18629186e1e9ecf1b0d9f',
|
||||
'0e5d146ba13101a1302d59ea6e6e0b3cace4ae38',
|
||||
|
||||
'pyyaml_version': '3.12',
|
||||
|
||||
@@ -52,6 +53,8 @@ vars = {
|
||||
|
||||
'mac_xcode_version': 'default',
|
||||
|
||||
'generate_location_tags': False,
|
||||
|
||||
# To allow running hooks without parsing the DEPS tree
|
||||
'process_deps': True,
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
13.0.0-beta.22
|
||||
13.6.4
|
||||
@@ -5,7 +5,7 @@
|
||||
[](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
|
||||
|
||||
@@ -64,7 +64,7 @@ steps:
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
# CalculateNativeWinOcclusion is disabled due to https://bugs.chromium.org/p/chromium/issues/detail?id=1139022
|
||||
node script/yarn test -- --enable-logging --verbose --disable-features=CalculateNativeWinOcclusion
|
||||
node script/yarn test -- --enable-logging --verbose --disable-features=CalculateNativeWinOcclusion --disable-gpu
|
||||
displayName: 'Run Electron tests'
|
||||
env:
|
||||
ELECTRON_OUT_DIR: Default
|
||||
|
||||
@@ -28,3 +28,8 @@ libcxx_abi_unstable = false
|
||||
enable_pseudolocales = false
|
||||
|
||||
is_cfi = false
|
||||
|
||||
# Make application name configurable at runtime for cookie crypto
|
||||
allow_runtime_configurable_key_storage = true
|
||||
|
||||
enable_cet_shadow_stack = false
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from collections import OrderedDict
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
@@ -49,8 +50,8 @@ const volatile char kFuseWire[] = { /* sentinel */ {sentinel}, /* fuse_version *
|
||||
}
|
||||
"""
|
||||
|
||||
with open(os.path.join(dir_path, "fuses.json"), 'r') as f:
|
||||
fuse_defaults = json.load(f)
|
||||
with open(os.path.join(dir_path, "fuses.json5"), 'r') as f:
|
||||
fuse_defaults = json.loads(''.join(line for line in f.readlines() if not line.strip()[0] == "/"), object_pairs_hook=OrderedDict)
|
||||
|
||||
fuse_version = fuse_defaults['_version']
|
||||
del fuse_defaults['_version']
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
"_comment": "Modifying the fuse schema in any breaking way should result in the _version prop being incremented. NEVER remove a fuse or change its meaning, instead mark it as removed with 'r'",
|
||||
"_schema": "0 == off, 1 == on, r == removed fuse",
|
||||
"_version": 1,
|
||||
"run_as_node": "1"
|
||||
"run_as_node": "1",
|
||||
"cookie_encryption": "0"
|
||||
}
|
||||
@@ -16,5 +16,5 @@ try:
|
||||
subprocess.check_output(args, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
error_msg = "NPM script '{}' failed with code '{}':\n".format(sys.argv[2], e.returncode)
|
||||
print(error_msg + e.output.decode('ascii'))
|
||||
print(error_msg + e.output.decode('utf8'))
|
||||
sys.exit(e.returncode)
|
||||
|
||||
15
build/zip.py
@@ -71,7 +71,7 @@ def execute(argv):
|
||||
raise e
|
||||
|
||||
def main(argv):
|
||||
dist_zip, runtime_deps, target_cpu, _, flatten_val = argv
|
||||
dist_zip, runtime_deps, target_cpu, _, flatten_val, flatten_relative_to = argv
|
||||
should_flatten = flatten_val == "true"
|
||||
dist_files = set()
|
||||
with open(runtime_deps) as f:
|
||||
@@ -98,11 +98,18 @@ def main(argv):
|
||||
if basename == 'chrome_sandbox'
|
||||
else dep
|
||||
)
|
||||
name_to_write = arcname
|
||||
if should_flatten:
|
||||
if flatten_relative_to:
|
||||
if name_to_write.startswith(flatten_relative_to):
|
||||
name_to_write = name_to_write[len(flatten_relative_to):]
|
||||
else:
|
||||
name_to_write = os.path.basename(arcname)
|
||||
else:
|
||||
name_to_write = os.path.basename(arcname)
|
||||
z.write(
|
||||
dep,
|
||||
os.path.basename(arcname)
|
||||
if should_flatten
|
||||
else arcname,
|
||||
name_to_write,
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
47
build/zip_libcxx.py
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
def execute(argv):
|
||||
try:
|
||||
output = subprocess.check_output(argv, stderr=subprocess.STDOUT)
|
||||
return output
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(e.output)
|
||||
raise e
|
||||
|
||||
def get_object_files(base_path, archive_name):
|
||||
archive_file = os.path.join(base_path, archive_name)
|
||||
output = execute(['nm', '-g', archive_file]).decode('ascii')
|
||||
object_files = set()
|
||||
lines = output.split("\n")
|
||||
for line in lines:
|
||||
if line.startswith(base_path):
|
||||
object_file = line.split(":")[0]
|
||||
object_files.add(object_file)
|
||||
if line.startswith('nm: '):
|
||||
object_file = line.split(":")[1].lstrip()
|
||||
object_files.add(object_file)
|
||||
return list(object_files) + [archive_file]
|
||||
|
||||
def main(argv):
|
||||
dist_zip, = argv
|
||||
out_dir = os.path.dirname(dist_zip)
|
||||
base_path_libcxx = os.path.join(out_dir, 'obj/buildtools/third_party/libc++')
|
||||
base_path_libcxxabi = os.path.join(out_dir, 'obj/buildtools/third_party/libc++abi')
|
||||
object_files_libcxx = get_object_files(base_path_libcxx, 'libc++.a')
|
||||
object_files_libcxxabi = get_object_files(base_path_libcxxabi, 'libc++abi.a')
|
||||
with zipfile.ZipFile(
|
||||
dist_zip, 'w', zipfile.ZIP_DEFLATED, allowZip64=True
|
||||
) as z:
|
||||
object_files_libcxx.sort()
|
||||
for object_file in object_files_libcxx:
|
||||
z.write(object_file, os.path.relpath(object_file, base_path_libcxx))
|
||||
for object_file in object_files_libcxxabi:
|
||||
z.write(object_file, os.path.relpath(object_file, base_path_libcxxabi))
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
@@ -66,8 +66,11 @@ static_library("chrome") {
|
||||
"//chrome/browser/extensions/global_shortcut_listener_win.cc",
|
||||
"//chrome/browser/extensions/global_shortcut_listener_win.h",
|
||||
"//chrome/browser/icon_loader_win.cc",
|
||||
"//chrome/browser/ui/frame/window_frame_util.h",
|
||||
"//chrome/browser/ui/view_ids.h",
|
||||
"//chrome/browser/win/chrome_process_finder.cc",
|
||||
"//chrome/browser/win/chrome_process_finder.h",
|
||||
"//chrome/browser/win/titlebar_config.h",
|
||||
"//chrome/child/v8_crashpad_support_win.cc",
|
||||
"//chrome/child/v8_crashpad_support_win.h",
|
||||
]
|
||||
@@ -145,6 +148,8 @@ static_library("chrome") {
|
||||
|
||||
if (enable_color_chooser) {
|
||||
sources += [
|
||||
"//chrome/browser/devtools/devtools_eye_dropper.cc",
|
||||
"//chrome/browser/devtools/devtools_eye_dropper.h",
|
||||
"//chrome/browser/platform_util.cc",
|
||||
"//chrome/browser/platform_util.h",
|
||||
"//chrome/browser/ui/browser_dialogs.h",
|
||||
@@ -345,17 +350,13 @@ source_set("plugins") {
|
||||
sources += [
|
||||
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.cc",
|
||||
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.h",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc",
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.h",
|
||||
]
|
||||
if (enable_pdf_viewer) {
|
||||
sources += [
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
|
||||
]
|
||||
if (enable_pdf_viewer) {
|
||||
deps += [ "//components/pdf/renderer" ]
|
||||
}
|
||||
deps += [ "//components/pdf/renderer" ]
|
||||
}
|
||||
deps += [
|
||||
"//components/strings",
|
||||
|
||||
@@ -18,20 +18,14 @@ an issue:
|
||||
|
||||
## Guides and Tutorials
|
||||
|
||||
### Quickstart
|
||||
### Getting started
|
||||
|
||||
* [Quick Start Guide](tutorial/quick-start.md)
|
||||
* [Prerequisites](tutorial/quick-start.md#prerequisites)
|
||||
* [Create a basic application](tutorial/quick-start.md#create-a-basic-application)
|
||||
* [Run your application](tutorial/quick-start.md#run-your-application)
|
||||
* [Package and distribute the application](tutorial/quick-start.md#package-and-distribute-the-application)
|
||||
* [Introduction](tutorial/introduction.md)
|
||||
* [Quick Start](tutorial/quick-start.md)
|
||||
* [Process Model](tutorial/process-model.md)
|
||||
|
||||
### Learning the basics
|
||||
|
||||
* [Electron's Process Model](tutorial/quick-start.md#application-architecture)
|
||||
* [Main and Renderer Processes](tutorial/quick-start.md#main-and-renderer-processes)
|
||||
* [Electron API](tutorial/quick-start.md#electron-api)
|
||||
* [Node.js API](tutorial/quick-start.md#nodejs-api)
|
||||
* Adding Features to Your App
|
||||
* [Notifications](tutorial/notifications.md)
|
||||
* [Recent Documents](tutorial/recent-documents.md)
|
||||
@@ -59,6 +53,7 @@ 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)
|
||||
|
||||
@@ -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` key is mapped to the `Windows` key on Windows and Linux and
|
||||
The `Super` (or `Meta`) key is mapped to the `Windows` key on Windows and Linux and
|
||||
`Cmd` on macOS.
|
||||
|
||||
## Available modifiers
|
||||
@@ -48,6 +48,7 @@ The `Super` key is mapped to the `Windows` key on Windows and Linux and
|
||||
* `AltGr`
|
||||
* `Shift`
|
||||
* `Super`
|
||||
* `Meta`
|
||||
|
||||
## Available key codes
|
||||
|
||||
|
||||
@@ -1193,8 +1193,8 @@ badge.
|
||||
|
||||
On macOS, it shows on the dock icon. On Linux, it only works for Unity launcher.
|
||||
|
||||
**Note:** Unity launcher requires the existence of a `.desktop` file to work,
|
||||
for more information please read [Desktop Environment Integration][unity-requirement].
|
||||
**Note:** Unity launcher requires a `.desktop` file to work. For more information,
|
||||
please read the [Unity integration documentation][unity-requirement].
|
||||
|
||||
### `app.getBadgeCount()` _Linux_ _macOS_
|
||||
|
||||
@@ -1432,8 +1432,8 @@ An `Integer` property that returns the badge count for current app. Setting the
|
||||
|
||||
On macOS, setting this with any nonzero integer shows on the dock icon. On Linux, this property only works for Unity launcher.
|
||||
|
||||
**Note:** Unity launcher requires the existence of a `.desktop` file to work,
|
||||
for more information please read [Desktop Environment Integration][unity-requirement].
|
||||
**Note:** Unity launcher requires a `.desktop` file to work. For more information,
|
||||
please read the [Unity integration documentation][unity-requirement].
|
||||
|
||||
**Note:** On macOS, you need to ensure that your application has the permission
|
||||
to display notifications for this property to take effect.
|
||||
@@ -1461,7 +1461,7 @@ A `Boolean` property that returns `true` if the app is packaged, `false` otherw
|
||||
[LSCopyDefaultHandlerForURLScheme]: https://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/#//apple_ref/c/func/LSCopyDefaultHandlerForURLScheme
|
||||
[handoff]: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html
|
||||
[activity-type]: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType
|
||||
[unity-requirement]: ../tutorial/desktop-environment-integration.md#unity-launcher
|
||||
[unity-requirement]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher
|
||||
[mas-builds]: ../tutorial/mac-app-store-submission-guide.md
|
||||
[Squirrel-Windows]: https://github.com/Squirrel/Squirrel.Windows
|
||||
[JumpListBeginListMSDN]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378398(v=vs.85).aspx
|
||||
|
||||
@@ -43,7 +43,7 @@ The installer generated with Squirrel will create a shortcut icon with an
|
||||
same ID for your app with `app.setAppUserModelId` API, otherwise Windows will
|
||||
not be able to pin your app properly in task bar.
|
||||
|
||||
Unlike Squirrel.Mac, Windows can host updates on S3 or any other static file host.
|
||||
Like Squirrel.Mac, Windows can host updates on S3 or any other static file host.
|
||||
You can read the documents of [Squirrel.Windows][squirrel-windows] to get more details
|
||||
about how Squirrel.Windows works.
|
||||
|
||||
|
||||
@@ -187,9 +187,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `parent` BrowserWindow (optional) - Specify parent window. Default is `null`.
|
||||
* `modal` Boolean (optional) - Whether this is a modal window. This only works when the
|
||||
window is a child window. Default is `false`.
|
||||
* `acceptFirstMouse` Boolean (optional) - Whether the web view accepts a single
|
||||
mouse-down event that simultaneously activates the window. Default is
|
||||
`false`.
|
||||
* `acceptFirstMouse` Boolean (optional) - Whether clicking an inactive window will also
|
||||
click through to the web contents. Default is `false` on macOS. This option is not
|
||||
configurable on other platforms.
|
||||
* `disableAutoHideCursor` Boolean (optional) - Whether to hide cursor when typing.
|
||||
Default is `false`.
|
||||
* `autoHideMenuBar` Boolean (optional) - Auto hide the menu bar unless the `Alt`
|
||||
@@ -213,16 +213,13 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `followWindow` - The backdrop should automatically appear active when the window is active, and inactive when it is not. This is the default.
|
||||
* `active` - The backdrop should always appear active.
|
||||
* `inactive` - The backdrop should always appear inactive.
|
||||
* `titleBarStyle` String (optional) - The style of window title bar.
|
||||
* `titleBarStyle` String (optional) _macOS_ _Windows_ - The style of window title bar.
|
||||
Default is `default`. Possible values are:
|
||||
* `default` - Results in the standard gray opaque Mac title
|
||||
bar.
|
||||
* `hidden` - Results in a hidden title bar and a full size content window, yet
|
||||
the title bar still has the standard window controls ("traffic lights") in
|
||||
the top left.
|
||||
* `hiddenInset` - Results in a hidden title bar with an alternative look
|
||||
* `default` - Results in the standard title bar for macOS or Windows respectively.
|
||||
* `hidden` - Results in a hidden title bar and a full size content window. On macOS, the window still has the standard window controls (“traffic lights”) in the top left. On Windows, when combined with `titleBarOverlay: true` it will activate the Window Controls Overlay (see `titleBarOverlay` for more information), otherwise no window controls will be shown.
|
||||
* `hiddenInset` - Only on macOS, results in a hidden title bar with an alternative look
|
||||
where the traffic light buttons are slightly more inset from the window edge.
|
||||
* `customButtonsOnHover` - Results in a hidden title bar and a full size
|
||||
* `customButtonsOnHover` - Only on macOS, results in a hidden title bar and a full size
|
||||
content window, the traffic light buttons will display when being hovered
|
||||
over in the top left of the window. **Note:** This option is currently
|
||||
experimental.
|
||||
@@ -238,7 +235,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
window shadow and window animations. Default is `true`.
|
||||
* `vibrancy` String (optional) - Add a type of vibrancy effect to the window, only on
|
||||
macOS. Can be `appearance-based`, `light`, `dark`, `titlebar`, `selection`,
|
||||
`menu`, `popover`, `sidebar`, `medium-light`, `ultra-dark`, `header`, `sheet`, `window`, `hud`, `fullscreen-ui`, `tooltip`, `content`, `under-window`, or `under-page`. Please note that using `frame: false` in combination with a vibrancy value requires that you use a non-default `titleBarStyle` as well. Also note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` are deprecated and have been removed in macOS Catalina (10.15).
|
||||
`menu`, `popover`, `sidebar`, `medium-light`, `ultra-dark`, `header`, `sheet`, `window`, `hud`, `fullscreen-ui`, `tooltip`, `content`, `under-window`, or `under-page`. Please note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` are deprecated and have been removed in macOS Catalina (10.15).
|
||||
* `zoomToPageWidth` Boolean (optional) - Controls the behavior on macOS when
|
||||
option-clicking the green stoplight button on the toolbar or by clicking the
|
||||
Window > Zoom menu item. If `true`, the window will grow to the preferred
|
||||
@@ -272,7 +269,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
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](sandbox-option.md).
|
||||
are more limited. Read more about the option [here](../tutorial/sandbox.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
|
||||
@@ -339,7 +336,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 `false`. The context that the `preload` script runs in will only have
|
||||
to `true`. 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
|
||||
@@ -351,8 +348,7 @@ 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`. The default
|
||||
is `false`. In Electron 12, the default will be changed to `true`. _Deprecated_
|
||||
can't unsafely cross between worlds when using `contextIsolation`. Defaults 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
|
||||
@@ -404,6 +400,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
contain the layout of the document—without requiring scrolling. Enabling
|
||||
this will cause the `preferred-size-changed` event to be emitted on the
|
||||
`WebContents` when the preferred size changes. Default is `false`.
|
||||
* `titleBarOverlay` [OverlayOptions](structures/overlay-options.md) | Boolean (optional) - When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS or using a `titleBarStyle` so that the standard window controls ("traffic lights" on macOS) are visible, this property enables the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and [CSS Environment Variables][overlay-css-env-vars]. Specifying `true` will result in an overlay with default system colors. Default is `false`. On Windows, the [OverlayOptions](structures/overlay-options.md) can be used instead of a boolean to specify colors for the overlay.
|
||||
|
||||
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
|
||||
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
|
||||
@@ -986,7 +983,7 @@ 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
|
||||
The aspect ratio is not respected when window is resized programmatically with
|
||||
APIs like `win.setSize`.
|
||||
|
||||
#### `win.setBackgroundColor(backgroundColor)`
|
||||
@@ -1382,7 +1379,7 @@ Captures a snapshot of the page within `rect`. Omitting `rect` will capture the
|
||||
* `httpReferrer` (String | [Referrer](structures/referrer.md)) (optional) - An HTTP Referrer URL.
|
||||
* `userAgent` String (optional) - A user agent originating the request.
|
||||
* `extraHeaders` String (optional) - Extra headers separated by "\n"
|
||||
* `postData` ([UploadRawData[]](structures/upload-raw-data.md) | [UploadFile[]](structures/upload-file.md)) (optional)
|
||||
* `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md))[] (optional)
|
||||
* `baseURLForDataURL` String (optional) - Base URL (with trailing path separator) for files to be loaded by the data URL. This is needed only if the specified `url` is a data URL and needs to load other files.
|
||||
|
||||
Returns `Promise<void>` - the promise will resolve when the page has finished loading
|
||||
@@ -1690,7 +1687,7 @@ current window into a top-level window.
|
||||
|
||||
#### `win.getParentWindow()`
|
||||
|
||||
Returns `BrowserWindow` - The parent window.
|
||||
Returns `BrowserWindow | null` - The parent window or `null` if there is no parent.
|
||||
|
||||
#### `win.getChildWindows()`
|
||||
|
||||
@@ -1810,3 +1807,5 @@ removed in future Electron releases.
|
||||
[window-levels]: https://developer.apple.com/documentation/appkit/nswindow/level
|
||||
[chrome-content-scripts]: https://developer.chrome.com/extensions/content_scripts#execution-environment
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[overlay-javascript-apis]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#javascript-apis
|
||||
[overlay-css-env-vars]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#css-environment-variables
|
||||
|
||||
@@ -71,7 +71,7 @@ const request = net.request({
|
||||
|
||||
Returns:
|
||||
|
||||
* `response` IncomingMessage - An object representing the HTTP response message.
|
||||
* `response` [IncomingMessage](incoming-message.md) - An object representing the HTTP response message.
|
||||
|
||||
#### Event: 'login'
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ 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`
|
||||
### --force-fieldtrials=`trials`
|
||||
|
||||
Field trials to be forcefully enabled or disabled.
|
||||
|
||||
@@ -142,7 +142,8 @@ proxy server flags that are passed.
|
||||
|
||||
### --no-sandbox
|
||||
|
||||
Disables Chromium sandbox, which is now enabled by default.
|
||||
Disables the Chromium [sandbox](https://www.chromium.org/developers/design-documents/sandbox).
|
||||
Forces renderer process and Chromium helper processes to run un-sandboxed.
|
||||
Should only be used for testing.
|
||||
|
||||
### --proxy-bypass-list=`hosts`
|
||||
|
||||
@@ -41,7 +41,7 @@ When `contextIsolation` is enabled in your `webPreferences` (this is the default
|
||||
|
||||
The `contextBridge` module has the following methods:
|
||||
|
||||
### `contextBridge.exposeInMainWorld(apiKey, api)` _Experimental_
|
||||
### `contextBridge.exposeInMainWorld(apiKey, api)`
|
||||
|
||||
* `apiKey` String - The key to inject the API onto `window` with. The API will be accessible on `window[apiKey]`.
|
||||
* `api` any - Your API, more information on what this API can be and how it works is available below.
|
||||
@@ -50,7 +50,7 @@ The `contextBridge` module has the following methods:
|
||||
|
||||
### API
|
||||
|
||||
The `api` provided to [`exposeInMainWorld`](#contextbridgeexposeinmainworldapikey-api-experimental) must be a `Function`, `String`, `Number`, `Array`, `Boolean`, or an object
|
||||
The `api` provided to [`exposeInMainWorld`](#contextbridgeexposeinmainworldapikey-api) must be a `Function`, `String`, `Number`, `Array`, `Boolean`, or an object
|
||||
whose keys are strings and values are a `Function`, `String`, `Number`, `Array`, `Boolean`, or another nested object that meets the same conditions.
|
||||
|
||||
`Function` values are proxied to the other context and all other values are **copied** and **frozen**. Any data / primitives sent in
|
||||
|
||||
@@ -24,7 +24,7 @@ The `dialog` module has the following methods:
|
||||
* `buttonLabel` String (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
use. The following values are supported:
|
||||
* `openFile` - Allow files to be selected.
|
||||
* `openDirectory` - Allow directories to be selected.
|
||||
@@ -87,7 +87,7 @@ dialog.showOpenDialogSync(mainWindow, {
|
||||
* `buttonLabel` String (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
use. The following values are supported:
|
||||
* `openFile` - Allow files to be selected.
|
||||
* `openDirectory` - Allow directories to be selected.
|
||||
@@ -112,7 +112,7 @@ Returns `Promise<Object>` - Resolve with an object containing the following:
|
||||
|
||||
* `canceled` Boolean - whether or not the dialog was canceled.
|
||||
* `filePaths` String[] - An array of file paths chosen by the user. If the dialog is cancelled this will be an empty array.
|
||||
* `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the `filePaths` array of base64 encoded strings which contains security scoped bookmark data. `securityScopedBookmarks` must be enabled for this to be populated. (For return values, see [table here](#bookmarks-array).)
|
||||
* `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the `filePaths` array of base64 encoded strings which contains security scoped bookmark data. `securityScopedBookmarks` must be enabled for this to be populated. (For return values, see [table here](#bookmarks-array).)
|
||||
|
||||
The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.
|
||||
|
||||
@@ -154,7 +154,7 @@ dialog.showOpenDialog(mainWindow, {
|
||||
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) (optional)
|
||||
* `options` Object
|
||||
* `title` String (optional)
|
||||
* `title` String (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
|
||||
* `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
|
||||
@@ -165,7 +165,7 @@ dialog.showOpenDialog(mainWindow, {
|
||||
displayed in front of the filename text field.
|
||||
* `showsTagField` Boolean (optional) _macOS_ - Show the tags input box,
|
||||
defaults to `true`.
|
||||
* `properties` String[] (optional)
|
||||
* `properties` String[] (optional)
|
||||
* `showHiddenFiles` - Show hidden files in dialog.
|
||||
* `createDirectory` _macOS_ - Allow creating new directories from dialog.
|
||||
* `treatPackageAsDirectory` _macOS_ - Treat packages, such as `.app` folders,
|
||||
@@ -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)
|
||||
* `title` String (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
|
||||
* `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
|
||||
@@ -195,7 +195,7 @@ The `filters` specifies an array of file types that can be displayed, see
|
||||
* `nameFieldLabel` String (optional) _macOS_ - Custom label for the text
|
||||
displayed in front of the filename text field.
|
||||
* `showsTagField` Boolean (optional) _macOS_ - Show the tags input box, defaults to `true`.
|
||||
* `properties` String[] (optional)
|
||||
* `properties` String[] (optional)
|
||||
* `showHiddenFiles` - Show hidden files in dialog.
|
||||
* `createDirectory` _macOS_ - Allow creating new directories from dialog.
|
||||
* `treatPackageAsDirectory` _macOS_ - Treat packages, such as `.app` folders,
|
||||
@@ -227,7 +227,7 @@ expanding and collapsing the dialog.
|
||||
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
|
||||
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
|
||||
`"error"` display the same warning icon.
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
will result in one button labeled "OK".
|
||||
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
|
||||
be selected by default when the message box opens.
|
||||
@@ -273,7 +273,7 @@ If `browserWindow` is not shown dialog will not be attached to it. In such case
|
||||
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
|
||||
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
|
||||
`"error"` display the same warning icon.
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
will result in one button labeled "OK".
|
||||
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
|
||||
be selected by default when the message box opens.
|
||||
|
||||
@@ -18,17 +18,17 @@ const win = new BrowserWindow({ width: 800, height: 600, frame: false })
|
||||
win.show()
|
||||
```
|
||||
|
||||
### Alternatives on macOS
|
||||
### Alternatives
|
||||
|
||||
There's an alternative way to specify a chromeless window.
|
||||
There's an alternative way to specify a chromeless window on macOS and Windows.
|
||||
Instead of setting `frame` to `false` which disables both the titlebar and window controls,
|
||||
you may want to have the title bar hidden and your content extend to the full window size,
|
||||
yet still preserve the window controls ("traffic lights") for standard window actions.
|
||||
yet still preserve the window controls ("traffic lights" on macOS) for standard window actions.
|
||||
You can do so by specifying the `titleBarStyle` option:
|
||||
|
||||
#### `hidden`
|
||||
|
||||
Results in a hidden title bar and a full size content window, yet the title bar still has the standard window controls (“traffic lights”) in the top left.
|
||||
Results in a hidden title bar and a full size content window. On macOS, the title bar still has the standard window controls (“traffic lights”) in the top left.
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
@@ -36,6 +36,8 @@ const win = new BrowserWindow({ titleBarStyle: 'hidden' })
|
||||
win.show()
|
||||
```
|
||||
|
||||
### Alternatives on macOS
|
||||
|
||||
#### `hiddenInset`
|
||||
|
||||
Results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge.
|
||||
@@ -61,6 +63,35 @@ const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: fa
|
||||
win.show()
|
||||
```
|
||||
|
||||
## Windows Control Overlay
|
||||
|
||||
When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS, using one of the `titleBarStyle`s as described above so
|
||||
that the traffic lights are visible, or using `titleBarStyle: hidden` on Windows, you can access the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and
|
||||
[CSS Environment Variables][overlay-css-env-vars] by setting the `titleBarOverlay` option to true. Specifying `true` will result in an overlay with default system colors.
|
||||
|
||||
On Windows, you can also specify the color of the overlay and its symbols by setting `titleBarOverlay` to an object with the options `color` and `symbolColor`. If an option is not specified, the color will default to its system color for the window control buttons:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow({
|
||||
titleBarStyle: 'hidden',
|
||||
titleBarOverlay: true
|
||||
})
|
||||
win.show()
|
||||
```
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow({
|
||||
titleBarStyle: 'hidden',
|
||||
titleBarOverlay: {
|
||||
color: '#2f3241',
|
||||
symbolColor: '#74b1be'
|
||||
}
|
||||
})
|
||||
win.show()
|
||||
```
|
||||
|
||||
## Transparent window
|
||||
|
||||
By setting the `transparent` option to `true`, you can also make the frameless
|
||||
@@ -186,3 +217,5 @@ behave correctly on all platforms you should never use a custom context menu on
|
||||
draggable areas.
|
||||
|
||||
[ignore-mouse-events]: browser-window.md#winsetignoremouseeventsignore-options
|
||||
[overlay-javascript-apis]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#javascript-apis
|
||||
[overlay-css-env-vars]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#css-environment-variables
|
||||
|
||||
@@ -162,7 +162,7 @@ const template = [
|
||||
{ role: 'services' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideothers' },
|
||||
{ role: 'hideOthers' },
|
||||
{ role: 'unhide' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'quit' }
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
# `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.
|
||||
@@ -506,6 +506,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
|
||||
* `permissionGranted` Boolean - Allow or deny the permission.
|
||||
* `details` Object - Some properties are only available on certain permission types.
|
||||
* `externalURL` String (optional) - The url of the `openExternal` request.
|
||||
* `securityOrigin` String (optional) - The security origin of the `media` request.
|
||||
* `mediaTypes` String[] (optional) - The types of media access being requested, elements can be `video`
|
||||
or `audio`
|
||||
* `requestingUrl` String - The last URL the requesting frame loaded
|
||||
@@ -531,7 +532,7 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
|
||||
#### `ses.setPermissionCheckHandler(handler)`
|
||||
|
||||
* `handler` Function\<Boolean> | null
|
||||
* `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.
|
||||
* `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. All cross origin sub frames making permission checks will pass a `null` webContents to this handler, while certain other permission checks such as `notifications` checks will always pass `null`. 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.
|
||||
|
||||
4
docs/api/structures/overlay-options.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# OverlayOptions Object
|
||||
|
||||
* `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled. Default is the system color.
|
||||
* `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled. Default is the system color.
|
||||
@@ -1,6 +1,6 @@
|
||||
# PostBody Object
|
||||
|
||||
* `data` Array<[PostData](./post-data.md)> - The post data to be sent to the
|
||||
* `data` ([UploadRawData](upload-raw-data.md) | [UploadFile](upload-file.md))[] - The post data to be sent to the
|
||||
new window.
|
||||
* `contentType` String - The `content-type` header used for the data. One of
|
||||
`application/x-www-form-urlencoded` or `multipart/form-data`. Corresponds to
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# PostData Object
|
||||
|
||||
* `type` String - One of the following:
|
||||
* `rawData` - The data is available as a `Buffer`, in the `rawData` field.
|
||||
* `file` - The object represents a file. The `filePath`, `offset`, `length`
|
||||
and `modificationTime` fields will be used to describe the file.
|
||||
* `blob` - The object represents a `Blob`. The `blobUUID` field will be used
|
||||
to describe the `Blob`.
|
||||
* `bytes` String (optional) - The raw bytes of the post data in a `Buffer`.
|
||||
Required for the `rawData` type.
|
||||
* `filePath` String (optional) - The path of the file being uploaded. Required
|
||||
for the `file` type.
|
||||
* `blobUUID` String (optional) - The `UUID` of the `Blob` being uploaded.
|
||||
Required for the `blob` type.
|
||||
* `offset` Integer (optional) - The offset from the beginning of the file being
|
||||
uploaded, in bytes. Only valid for `file` types.
|
||||
* `length` Integer (optional) - The length of the file being uploaded, in bytes.
|
||||
If set to `-1`, the whole file will be uploaded. Only valid for `file` types.
|
||||
* `modificationTime` Double (optional) - The modification time of the file
|
||||
represented by a double, which is the number of seconds since the `UNIX Epoch`
|
||||
(Jan 1, 1970). Only valid for `file` types.
|
||||
@@ -13,7 +13,7 @@ either process type.
|
||||
|
||||
The basic rule is: if a module is [GUI][gui] or low-level system related, then
|
||||
it should be only available in the main process. You need to be familiar with
|
||||
the concept of [main process vs. renderer process](../tutorial/quick-start.md#main-and-renderer-processes)
|
||||
the concept of main process vs. renderer process
|
||||
scripts to be able to use those modules.
|
||||
|
||||
The main process script is like a normal Node.js script:
|
||||
@@ -43,8 +43,6 @@ extra ability to use node modules if `nodeIntegration` is enabled:
|
||||
</html>
|
||||
```
|
||||
|
||||
To run your app, read [Run your app](../tutorial/quick-start.md#run-your-application).
|
||||
|
||||
## Destructuring assignment
|
||||
|
||||
As of 0.37, you can use
|
||||
|
||||
@@ -14,7 +14,7 @@ Process: [Main](../glossary.md#main-process)
|
||||
* `highlightedIndex` Integer - The index of the item the user touched.
|
||||
* `selectedStyle` String (optional) - Selected item style. Can be `background`, `outline` or `none`. Defaults to `none`.
|
||||
* `overlayStyle` String (optional) - Selected overlay item style. Can be `background`, `outline` or `none`. Defaults to `none`.
|
||||
* `showArrowButtons` Boolean (optional) - Defaults to `false`.
|
||||
* `showArrowButtons` Boolean (optional) - Whether to show arrow buttons. Defaults to `false` and is only shown if `items` is non-empty.
|
||||
* `mode` String (optional) - Can be `fixed` or `free`. The default is `free`.
|
||||
* `continuous` Boolean (optional) - Defaults to `true`.
|
||||
|
||||
|
||||
@@ -45,6 +45,26 @@ returns `null`.
|
||||
Returns `WebContents` | undefined - A WebContents instance with the given ID, or
|
||||
`undefined` if there is no WebContents associated with the given ID.
|
||||
|
||||
### `webContents.fromDevToolsTargetId(targetId)`
|
||||
|
||||
* `targetId` String - The Chrome DevTools Protocol [TargetID](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID) associated with the WebContents instance.
|
||||
|
||||
Returns `WebContents` | undefined - A WebContents instance with the given TargetID, or
|
||||
`undefined` if there is no WebContents associated with the given TargetID.
|
||||
|
||||
When communicating with the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/),
|
||||
it can be useful to lookup a WebContents instance based on its assigned TargetID.
|
||||
|
||||
```js
|
||||
async function lookupTargetId (browserWindow) {
|
||||
const wc = browserWindow.webContents
|
||||
await wc.debugger.attach('1.3')
|
||||
const { targetInfo } = await wc.debugger.sendCommand('Target.getTargetInfo')
|
||||
const { targetId } = targetInfo
|
||||
const targetWebContents = await webContents.fromDevToolsTargetId(targetId)
|
||||
}
|
||||
```
|
||||
|
||||
## Class: WebContents
|
||||
|
||||
> Render and control the contents of a BrowserWindow instance.
|
||||
@@ -710,6 +730,8 @@ first available device will be selected. `callback` should be called with
|
||||
`deviceId` to be selected, passing empty string to `callback` will
|
||||
cancel the request.
|
||||
|
||||
If no event listener is added for this event, all bluetooth requests will be cancelled.
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
@@ -914,7 +936,7 @@ in `webPreferences`.
|
||||
* `httpReferrer` (String | [Referrer](structures/referrer.md)) (optional) - An HTTP Referrer url.
|
||||
* `userAgent` String (optional) - A user agent originating the request.
|
||||
* `extraHeaders` String (optional) - Extra headers separated by "\n".
|
||||
* `postData` ([UploadRawData[]](structures/upload-raw-data.md) | [UploadFile[]](structures/upload-file.md)) (optional)
|
||||
* `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md))[] (optional)
|
||||
* `baseURLForDataURL` String (optional) - Base url (with trailing path separator) for files to be loaded by the data url. This is needed only if the specified `url` is a data url and needs to load other files.
|
||||
|
||||
Returns `Promise<void>` - the promise will resolve when the page has finished loading
|
||||
@@ -1184,6 +1206,15 @@ 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()`.
|
||||
* `disposition` String - Can be `default`, `foreground-tab`, `background-tab`,
|
||||
`new-window`, `save-to-disk` or `other`.
|
||||
* `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`.
|
||||
|
||||
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.
|
||||
@@ -1321,8 +1352,7 @@ 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 the operation is first request or a follow up,
|
||||
defaults to `false`.
|
||||
* `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`.
|
||||
* `matchCase` Boolean (optional) - Whether search should be case-sensitive,
|
||||
defaults to `false`.
|
||||
|
||||
|
||||
@@ -62,6 +62,11 @@ Sets the maximum and minimum pinch-to-zoom level.
|
||||
> webFrame.setVisualZoomLevelLimits(1, 3)
|
||||
> ```
|
||||
|
||||
> **NOTE**: Visual zoom only applies to pinch-to-zoom behavior. Cmd+/-/0 zoom shortcuts are
|
||||
> controlled by the 'zoomIn', 'zoomOut', and 'resetZoom' MenuItem roles in the application
|
||||
> Menu. To disable shortcuts, manually [define the Menu](./menu.md#examples) and omit zoom roles
|
||||
> from the definition.
|
||||
|
||||
### `webFrame.setSpellCheckProvider(language, provider)`
|
||||
|
||||
* `language` String
|
||||
|
||||
@@ -154,7 +154,6 @@ response are visible by the time this listener is fired.
|
||||
* `timestamp` Double
|
||||
* `statusLine` String
|
||||
* `statusCode` Integer
|
||||
* `requestHeaders` Record<string, string>
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `callback` Function
|
||||
* `headersReceivedResponse` Object
|
||||
|
||||
@@ -151,12 +151,16 @@ browser plugins. Plugins are disabled by default.
|
||||
### `preload`
|
||||
|
||||
```html
|
||||
<!-- from a file -->
|
||||
<webview src="https://www.github.com/" preload="./test.js"></webview>
|
||||
<!-- or if you want to load from an asar archive -->
|
||||
<webview src="https://www.github.com/" preload="./app.asar/test.js"></webview>
|
||||
```
|
||||
|
||||
A `String` that specifies a script that will be loaded before other scripts run in the guest
|
||||
page. The protocol of script's URL must be either `file:` or `asar:`, because it
|
||||
will be loaded by `require` in guest page under the hood.
|
||||
page. The protocol of script's URL must be `file:` (even when using `asar:` archives) because
|
||||
it will be loaded by Node's `require` under the hood, which treats `asar:` archives as virtual
|
||||
directories.
|
||||
|
||||
When the guest page doesn't have node integration this script will still have
|
||||
access to all Node APIs, but global objects injected by Node will be deleted
|
||||
@@ -274,7 +278,7 @@ webview.addEventListener('dom-ready', () => {
|
||||
* `httpReferrer` (String | [Referrer](structures/referrer.md)) (optional) - An HTTP Referrer url.
|
||||
* `userAgent` String (optional) - A user agent originating the request.
|
||||
* `extraHeaders` String (optional) - Extra headers separated by "\n"
|
||||
* `postData` ([UploadRawData[]](structures/upload-raw-data.md) | [UploadFile[]](structures/upload-file.md)) (optional)
|
||||
* `postData` ([UploadRawData](structures/upload-raw-data.md) | [UploadFile](structures/upload-file.md))[] (optional)
|
||||
* `baseURLForDataURL` String (optional) - Base url (with trailing path separator) for files to be loaded by the data url. This is needed only if the specified `url` is a data url and needs to load other files.
|
||||
|
||||
Returns `Promise<void>` - The promise will resolve when the page has finished loading
|
||||
@@ -515,8 +519,7 @@ 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 the operation is first request or a follow up,
|
||||
defaults to `false`.
|
||||
* `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`.
|
||||
* `matchCase` Boolean (optional) - Whether search should be case-sensitive,
|
||||
defaults to `false`.
|
||||
|
||||
@@ -719,6 +722,10 @@ Corresponds to the points in time when the spinner of the tab starts spinning.
|
||||
|
||||
Corresponds to the points in time when the spinner of the tab stops spinning.
|
||||
|
||||
### Event: 'did-attach'
|
||||
|
||||
Fired when attached to the embedder web contents.
|
||||
|
||||
### Event: 'dom-ready'
|
||||
|
||||
Fired when document in the given frame is loaded.
|
||||
@@ -839,6 +846,19 @@ this purpose.
|
||||
|
||||
Calling `event.preventDefault()` does __NOT__ have any effect.
|
||||
|
||||
### Event: 'did-start-navigation'
|
||||
|
||||
Returns:
|
||||
|
||||
* `url` String
|
||||
* `isInPlace` Boolean
|
||||
* `isMainFrame` Boolean
|
||||
* `frameProcessId` Integer
|
||||
* `frameRoutingId` Integer
|
||||
|
||||
Emitted when any frame (including main) starts navigating. `isInPlace` will be
|
||||
`true` for in-page navigations.
|
||||
|
||||
### Event: 'did-navigate'
|
||||
|
||||
Returns:
|
||||
@@ -851,6 +871,23 @@ This event is not emitted for in-page navigations, such as clicking anchor links
|
||||
or updating the `window.location.hash`. Use `did-navigate-in-page` event for
|
||||
this purpose.
|
||||
|
||||
### Event: 'did-frame-navigate'
|
||||
|
||||
Returns:
|
||||
|
||||
* `url` String
|
||||
* `httpResponseCode` Integer - -1 for non HTTP navigations
|
||||
* `httpStatusText` String - empty for non HTTP navigations,
|
||||
* `isMainFrame` Boolean
|
||||
* `frameProcessId` Integer
|
||||
* `frameRoutingId` Integer
|
||||
|
||||
Emitted when any frame navigation is done.
|
||||
|
||||
This event is not emitted for in-page navigations, such as clicking anchor links
|
||||
or updating the `window.location.hash`. Use `did-navigate-in-page` event for
|
||||
this purpose.
|
||||
|
||||
### Event: 'did-navigate-in-page'
|
||||
|
||||
Returns:
|
||||
@@ -967,3 +1004,78 @@ 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/
|
||||
|
||||
### Event: 'context-menu'
|
||||
|
||||
Returns:
|
||||
|
||||
* `params` Object
|
||||
* `x` Integer - x coordinate.
|
||||
* `y` Integer - y coordinate.
|
||||
* `linkURL` String - URL of the link that encloses the node the context menu
|
||||
was invoked on.
|
||||
* `linkText` String - Text associated with the link. May be an empty
|
||||
string if the contents of the link are an image.
|
||||
* `pageURL` String - URL of the top level page that the context menu was
|
||||
invoked on.
|
||||
* `frameURL` String - URL of the subframe that the context menu was invoked
|
||||
on.
|
||||
* `srcURL` String - Source URL for the element that the context menu
|
||||
was invoked on. Elements with source URLs are images, audio and video.
|
||||
* `mediaType` String - Type of the node the context menu was invoked on. Can
|
||||
be `none`, `image`, `audio`, `video`, `canvas`, `file` or `plugin`.
|
||||
* `hasImageContents` Boolean - Whether the context menu was invoked on an image
|
||||
which has non-empty contents.
|
||||
* `isEditable` Boolean - Whether the context is editable.
|
||||
* `selectionText` String - Text of the selection that the context menu 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
|
||||
word and spellchecker is enabled.
|
||||
* `frameCharset` String - The character encoding of the frame on which the
|
||||
menu was invoked.
|
||||
* `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`, `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.
|
||||
* `isPaused` Boolean - Whether the media element is paused.
|
||||
* `isMuted` Boolean - Whether the media element is muted.
|
||||
* `hasAudio` Boolean - Whether the media element has audio.
|
||||
* `isLooping` Boolean - Whether the media element is looping.
|
||||
* `isControlsVisible` Boolean - Whether the media element's controls are
|
||||
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.
|
||||
* `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.
|
||||
|
||||
@@ -117,15 +117,18 @@ const mainWindow = new BrowserWindow({
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
if (url === 'about:blank') {
|
||||
return {
|
||||
frame: false,
|
||||
fullscreenable: false,
|
||||
backgroundColor: 'black',
|
||||
webPreferences: {
|
||||
preload: 'my-child-window-preload-script.js'
|
||||
action: 'allow',
|
||||
overrideBrowserWindowOptions: {
|
||||
frame: false,
|
||||
fullscreenable: false,
|
||||
backgroundColor: 'black',
|
||||
webPreferences: {
|
||||
preload: 'my-child-window-preload-script.js'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
return { action: 'deny' }
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ files, you need to have built Electron so that it knows which compiler flags
|
||||
were used. There is one required option for the script `--output-dir`, which
|
||||
tells the script which build directory to pull the compilation information
|
||||
from. A typical usage would be:
|
||||
`npm run lint:clang-tiy --out-dir ../out/Testing`
|
||||
`npm run lint:clang-tidy --out-dir ../out/Testing`
|
||||
|
||||
With no filenames provided, all C/C++/Objective-C files will be checked.
|
||||
You can provide a list of files to be checked by passing the filenames after
|
||||
the options:
|
||||
`npm run lint:clang-tiy --out-dir ../out/Testing shell/browser/api/electron_api_app.cc`
|
||||
`npm run lint:clang-tidy --out-dir ../out/Testing shell/browser/api/electron_api_app.cc`
|
||||
|
||||
While `clang-tidy` has a
|
||||
[long list](https://clang.llvm.org/extra/clang-tidy/checks/list.html)
|
||||
|
||||
@@ -25,7 +25,7 @@ You can run `npm run lint` to show any style issues detected by `cpplint` and
|
||||
## C++ and Python
|
||||
|
||||
For C++ and Python, we follow Chromium's [Coding
|
||||
Style](https://www.chromium.org/developers/coding-style). You can use
|
||||
Style](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/styleguide.md). You can use
|
||||
[clang-format](clang-format.md) to format the C++ code automatically. There is
|
||||
also a script `script/cpplint.py` to check whether all files conform.
|
||||
|
||||
|
||||
@@ -26,7 +26,9 @@ you prefer a graphical interface.
|
||||
* **.lldbinit**: Create or edit `~/.lldbinit` to allow Chromium code to be properly source-mapped.
|
||||
|
||||
```text
|
||||
command script import ~/electron/src/tools/lldb/lldbinit.py
|
||||
# e.g: ['~/electron/src/tools/lldb']
|
||||
script sys.path[:0] = ['<...path/to/electron/src/tools/lldb>']
|
||||
script import lldbinit
|
||||
```
|
||||
|
||||
## Attaching to and Debugging Electron
|
||||
|
||||
@@ -7,12 +7,9 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<a href="#" id="drag">Drag me</a>
|
||||
<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>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
const { app, BrowserWindow, ipcMain, nativeImage, NativeImage } = require('electron')
|
||||
const fs = require('fs');
|
||||
const http = require('http');
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const https = require('https')
|
||||
|
||||
function createWindow () {
|
||||
function createWindow() {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
const iconName = 'iconForDragAndDrop.png';
|
||||
const icon = fs.createWriteStream(`${process.cwd()}/${iconName}`);
|
||||
http.get('http://img.icons8.com/ios/452/drag-and-drop.png', (response) => {
|
||||
|
||||
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) => {
|
||||
response.pipe(icon);
|
||||
});
|
||||
|
||||
@@ -23,8 +30,8 @@ app.whenReady().then(createWindow)
|
||||
|
||||
ipcMain.on('ondragstart', (event, filePath) => {
|
||||
event.sender.startDrag({
|
||||
file: filePath,
|
||||
icon: `${process.cwd()}/${iconName}`
|
||||
file: path.join(__dirname, filePath),
|
||||
icon: iconName,
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
8
docs/fiddles/features/drag-and-drop/preload.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
startDrag: (fileName) => {
|
||||
ipcRenderer.send('ondragstart', fileName)
|
||||
}
|
||||
})
|
||||
@@ -1,9 +1,9 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
const fs = require('fs')
|
||||
|
||||
document.getElementById('drag').ondragstart = (event) => {
|
||||
const fileName = 'drag-and-drop.md'
|
||||
fs.writeFileSync(fileName, '# Test drag and drop');
|
||||
document.getElementById('drag1').ondragstart = (event) => {
|
||||
event.preventDefault()
|
||||
ipcRenderer.send('ondragstart', process.cwd() + `/${fileName}`)
|
||||
window.electron.startDrag('drag-and-drop-1.md')
|
||||
}
|
||||
|
||||
document.getElementById('drag2').ondragstart = (event) => {
|
||||
event.preventDefault()
|
||||
window.electron.startDrag('drag-and-drop-2.md')
|
||||
}
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<p>Hit Alt+Ctrl+I on Windows or Opt+Cmd+I on Mac to see a message printed to the console.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,9 +4,6 @@ function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
<p>Hit Ctrl+I to see a message printed to the console.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } })
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
|
||||
win.loadFile('index.html')
|
||||
win.webContents.on('before-input-event', (event, input) => {
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<p>Hit Alt+Shift+I on Windows, or Opt+Cmd+I on mac to see a message printed to the console.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,9 +4,6 @@ function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
|
||||
17
docs/fiddles/features/keyboard-shortcuts/web-apis/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
|
||||
<p>Hit any key with this window focused to see it captured here.</p>
|
||||
<div><span>Last Key Pressed: </span><span id="last-keypress"></span></div>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
35
docs/fiddles/features/keyboard-shortcuts/web-apis/main.js
Normal file
@@ -0,0 +1,35 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const {app, BrowserWindow} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
function handleKeyPress (event) {
|
||||
// You can put code here to handle the keypress.
|
||||
document.getElementById("last-keypress").innerText = event.key
|
||||
console.log(`You pressed ${event.key}`)
|
||||
}
|
||||
|
||||
window.addEventListener('keyup', handleKeyPress, true)
|
||||
@@ -1,11 +1,12 @@
|
||||
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -21,20 +22,22 @@ function createWindow () {
|
||||
})
|
||||
|
||||
ipcMain.handle('dark-mode:system', () => {
|
||||
nativeTheme.themeSouce = 'system'
|
||||
nativeTheme.themeSource = 'system'
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
6
docs/fiddles/features/macos-dark-mode/preload.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('darkMode', {
|
||||
toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
|
||||
system: () => ipcRenderer.invoke('dark-mode:system')
|
||||
})
|
||||
@@ -1,11 +1,9 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
|
||||
const isDarkMode = await ipcRenderer.invoke('dark-mode:toggle')
|
||||
const isDarkMode = await window.darkMode.toggle()
|
||||
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
|
||||
})
|
||||
|
||||
document.getElementById('reset-to-system').addEventListener('click', async () => {
|
||||
await ipcRenderer.invoke('dark-mode:system')
|
||||
await window.darkMode.system()
|
||||
document.getElementById('theme-source').innerHTML = 'System'
|
||||
})
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<p>Right click the dock icon to see the custom menu options.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,9 +4,6 @@ function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
@@ -27,7 +24,9 @@ const dockMenu = Menu.buildFromTemplate([
|
||||
])
|
||||
|
||||
app.whenReady().then(() => {
|
||||
app.dock.setMenu(dockMenu)
|
||||
if (process.platform === 'darwin') {
|
||||
app.dock.setMenu(dockMenu)
|
||||
}
|
||||
}).then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<p>After launching this application, you should see the system notification.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -3,21 +3,17 @@ const { app, BrowserWindow, Notification } = require('electron')
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
const NOTIFICATION_TITLE = 'Basic Notification'
|
||||
const NOTIFICATION_BODY = 'Notification from the Main process'
|
||||
|
||||
function showNotification () {
|
||||
const notification = {
|
||||
title: 'Basic Notification',
|
||||
body: 'Notification from the Main process'
|
||||
}
|
||||
new Notification(notification).show()
|
||||
new Notification({ title: NOTIFICATION_TITLE, body: NOTIFICATION_BODY }).show()
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow).then(showNotification)
|
||||
|
||||
@@ -7,11 +7,9 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<p>After launching this application, you should see the system notification.</p>
|
||||
<p id="output">Click it to see the effect in this interface.</p>
|
||||
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -3,10 +3,7 @@ const { app, BrowserWindow } = require('electron')
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const myNotification = new Notification('Title', {
|
||||
body: 'Notification from the Renderer process'
|
||||
})
|
||||
const NOTIFICATION_TITLE = 'Title'
|
||||
const NOTIFICATION_BODY = 'Notification from the Renderer process. Click to log to console.'
|
||||
const CLICK_MESSAGE = 'Notification clicked!'
|
||||
|
||||
myNotification.onclick = () => {
|
||||
console.log('Notification clicked')
|
||||
}
|
||||
new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY })
|
||||
.onclick = () => document.getElementById("output").innerText = CLICK_MESSAGE
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +1,6 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
app.disableHardwareAcceleration()
|
||||
|
||||
@@ -12,7 +13,7 @@ app.whenReady().then(() => {
|
||||
fs.writeFileSync('ex.png', image.toPNG())
|
||||
})
|
||||
win.webContents.setFrameRate(60)
|
||||
console.log(`The screenshot has been successfully saved to ${process.cwd()}/ex.png`)
|
||||
console.log(`The screenshot has been successfully saved to ${path.join(process.cwd(), 'ex.png')}`)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
|
||||
13
docs/fiddles/features/online-detection/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Connection status: <strong id='status'></strong></h1>
|
||||
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
26
docs/fiddles/features/online-detection/main.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
function createWindow () {
|
||||
const onlineStatusWindow = new BrowserWindow({
|
||||
width: 300,
|
||||
height: 200
|
||||
})
|
||||
|
||||
onlineStatusWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
const { app, BrowserWindow, ipcMain } = require('electron')
|
||||
|
||||
let onlineStatusWindow
|
||||
|
||||
app.whenReady().then(() => {
|
||||
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false, webPreferences: { nodeIntegration: true } })
|
||||
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
|
||||
})
|
||||
|
||||
ipcMain.on('online-status-changed', (event, status) => {
|
||||
console.log(status)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
@@ -1,7 +0,0 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
const updateOnlineStatus = () => { ipcRenderer.send('online-status-changed', navigator.onLine ? 'online' : 'offline') }
|
||||
|
||||
window.addEventListener('online', updateOnlineStatus)
|
||||
window.addEventListener('offline', updateOnlineStatus)
|
||||
|
||||
updateOnlineStatus()
|
||||
8
docs/fiddles/features/online-detection/renderer.js
Normal file
@@ -0,0 +1,8 @@
|
||||
function onlineStatusIndicator () {
|
||||
document.getElementById('status').innerHTML = navigator.onLine ? 'online' : 'offline'
|
||||
}
|
||||
|
||||
window.addEventListener('online', onlineStatusIndicator)
|
||||
window.addEventListener('offline', onlineStatusIndicator)
|
||||
|
||||
onlineStatusIndicator()
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,20 +0,0 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let onlineStatusWindow
|
||||
|
||||
app.whenReady().then(() => {
|
||||
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false })
|
||||
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
@@ -1,6 +0,0 @@
|
||||
const alertOnlineStatus = () => { window.alert(navigator.onLine ? 'online' : 'offline') }
|
||||
|
||||
window.addEventListener('online', alertOnlineStatus)
|
||||
window.addEventListener('offline', alertOnlineStatus)
|
||||
|
||||
alertOnlineStatus()
|
||||
@@ -7,10 +7,9 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<p>Keep an eye on the dock (Mac) or taskbar (Windows, Unity) for this application!</p>
|
||||
<p>It should indicate a progress that advances from 0 to 100%.</p>
|
||||
<p>It should then show indeterminate (Windows) or pin at 100% (other operating systems)
|
||||
briefly and then loop.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,21 +1,39 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let progressInterval
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
win.setProgressBar(0.5)
|
||||
}
|
||||
|
||||
const INCREMENT = 0.03
|
||||
const INTERVAL_DELAY = 100 // ms
|
||||
|
||||
let c = 0
|
||||
progressInterval = setInterval(() => {
|
||||
// update progress bar to next value
|
||||
// values between 0 and 1 will show progress, >1 will show indeterminate or stick at 100%
|
||||
win.setProgressBar(c)
|
||||
|
||||
// increment or reset progress bar
|
||||
if (c < 2) {
|
||||
c += INCREMENT
|
||||
} else {
|
||||
c = (-INCREMENT * 5) // reset to a bit less than 0 to show reset state
|
||||
}
|
||||
}, INTERVAL_DELAY)
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// before the app is terminated, clear both timers
|
||||
app.on('before-quit', () => {
|
||||
clearInterval(progressInterval)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<title>Recent Documents</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<h1>Recent Documents</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
Right click on the app icon to see recent documents.
|
||||
You should see `recently-used.md` added to the list of recent files
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -5,17 +5,15 @@ const path = require('path')
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
const fileName = 'recently-used.md'
|
||||
fs.writeFile(fileName, 'Lorem Ipsum', () => {
|
||||
app.addRecentDocument(path.join(process.cwd(), `${fileName}`))
|
||||
app.addRecentDocument(path.join(__dirname, fileName))
|
||||
})
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
<link rel="stylesheet" type="text/css" href="./styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
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>.
|
||||
Click on the title with the <pre>Command</pre> or <pre>Control</pre> key pressed.
|
||||
You should see a popup with the represented file at the top.
|
||||
</p>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,10 +4,7 @@ const os = require('os');
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
|
||||
@@ -16,91 +16,12 @@
|
||||
<p>
|
||||
Open the
|
||||
<a href="https://electronjs.org/docs/api/tray">
|
||||
full API documentation (opens in new window)
|
||||
full API documentation
|
||||
</a>
|
||||
in your browser.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<button id="put-in-tray">View Demo</button>
|
||||
<span id="tray-countdown"></span>
|
||||
</div>
|
||||
<p>
|
||||
The demo button sends a message to the main process using the
|
||||
<code>ipc</code> module. In the main process the app is told to
|
||||
place an icon, with a context menu, in the tray.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In this example the tray icon can be removed by clicking 'Remove' in
|
||||
the context menu or selecting the demo button again.
|
||||
</p>
|
||||
<h5>Main Process</h5>
|
||||
<pre>
|
||||
<code>
|
||||
const path = require('path')
|
||||
const {ipcMain, app, Menu, Tray} = require('electron')
|
||||
|
||||
let appIcon = null
|
||||
|
||||
ipcMain.on('put-in-tray', (event) => {
|
||||
const iconName = process.platform === 'win32' ? 'windows-icon.png' : 'iconTemplate.png'
|
||||
const iconPath = path.join(__dirname, iconName)
|
||||
appIcon = new Tray(iconPath)
|
||||
|
||||
const contextMenu = Menu.buildFromTemplate([{
|
||||
label: 'Remove',
|
||||
click: () => {
|
||||
event.sender.send('tray-removed')
|
||||
}
|
||||
}])
|
||||
|
||||
appIcon.setToolTip('Electron Demo in the tray.')
|
||||
appIcon.setContextMenu(contextMenu)
|
||||
})
|
||||
|
||||
ipcMain.on('remove-tray', () => {
|
||||
appIcon.destroy()
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (appIcon) appIcon.destroy()
|
||||
})
|
||||
</code>
|
||||
</pre>
|
||||
<h5>Renderer Process</h5>
|
||||
<pre>
|
||||
<code>
|
||||
const ipc = require('electron').ipcRenderer
|
||||
|
||||
const trayBtn = document.getElementById('put-in-tray')
|
||||
let trayOn = false
|
||||
|
||||
trayBtn.addEventListener('click', function (event) {
|
||||
if (trayOn) {
|
||||
trayOn = false
|
||||
document.getElementById('tray-countdown').innerHTML = ''
|
||||
ipc.send('remove-tray')
|
||||
} else {
|
||||
trayOn = true
|
||||
const message = 'Click demo again to remove.'
|
||||
document.getElementById('tray-countdown').innerHTML = message
|
||||
ipc.send('put-in-tray')
|
||||
}
|
||||
})
|
||||
// Tray removed from context menu on icon
|
||||
ipc.on('tray-removed', function () {
|
||||
ipc.send('remove-tray')
|
||||
trayOn = false
|
||||
document.getElementById('tray-countdown').innerHTML = ''
|
||||
})
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<div>
|
||||
<h2>ProTip</h2>
|
||||
<strong>Tray support in Linux.</strong>
|
||||
@@ -109,7 +30,7 @@ ipc.on('tray-removed', function () {
|
||||
will need to install <code>libappindicator1</code> to make the
|
||||
tray icon work. See the
|
||||
<a href="https://electronjs.org/docs/api/tray">
|
||||
full API documentation (opens in new window)
|
||||
full API documentation
|
||||
</a>
|
||||
for more details about using Tray on Linux.
|
||||
</p>
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
const { ipcRenderer, shell } = require('electron')
|
||||
|
||||
const trayBtn = document.getElementById('put-in-tray')
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
let trayOn = false
|
||||
|
||||
trayBtn.addEventListener('click', function (event) {
|
||||
if (trayOn) {
|
||||
trayOn = false
|
||||
document.getElementById('tray-countdown').innerHTML = ''
|
||||
ipcRenderer.send('remove-tray')
|
||||
} else {
|
||||
trayOn = true
|
||||
const message = 'Click demo again to remove.'
|
||||
document.getElementById('tray-countdown').innerHTML = message
|
||||
ipcRenderer.send('put-in-tray')
|
||||
}
|
||||
})
|
||||
// Tray removed from context menu on icon
|
||||
ipcRenderer.on('tray-removed', function () {
|
||||
ipcRenderer.send('remove-tray')
|
||||
trayOn = false
|
||||
document.getElementById('tray-countdown').innerHTML = ''
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -1,92 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>app.setAsDefaultProtocol Demo</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section>
|
||||
<header>
|
||||
<h1>
|
||||
Protocol Handler
|
||||
</h1>
|
||||
<h3>The <code>app</code> module provides methods for handling protocols.</h3>
|
||||
<p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a browser asks to be your default for viewing web pages.</p>
|
||||
<h1>App Default Protocol Demo</h1>
|
||||
|
||||
<p>Open the <a href="https://electronjs.org/docs/api/app">full app API documentation<span class="u-visible-to-screen-reader">(opens in new window)</span></a> in your browser.</p>
|
||||
</header>
|
||||
<p>The protocol API allows us to register a custom protocol and intercept existing protocol requests.</p>
|
||||
<p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a
|
||||
browser asks to be your default for viewing web pages.</p>
|
||||
|
||||
<div >
|
||||
<button id="open-in-browser" class="js-container-target demo-toggle-button">Launch current page in browser
|
||||
<div class="demo-meta u-avoid-clicks">Supports: Win, macOS <span class="demo-meta-divider">|</span> Process: Main</div>
|
||||
</button>
|
||||
<section id='open-app-link'>
|
||||
<a href="electron-api-demos://open">Now... launch the app from a web link</a>
|
||||
</section>
|
||||
<div >
|
||||
<p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app as the default for <code>electron-api-demos://</code>. The demo button above will launch a page in your default browser with a link. Click that link and it will re-launch this app.</p>
|
||||
<h5>Packaging</h5>
|
||||
<p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code> for the app is updated to include the new protocol handler. If you're using <code>electron-packager</code> then you can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this app is below.</p>
|
||||
<h5>Renderer Process</h5>
|
||||
<pre><code>
|
||||
const {shell} = require('electron')
|
||||
const path = require('path')
|
||||
const protocolHandlerBtn = document.getElementById('protocol-handler')
|
||||
protocolHandlerBtn.addEventListener('click', () => {
|
||||
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
|
||||
const pagePath = path.join('file://', pageDirectory, '../../sections/system/protocol-link.html')
|
||||
shell.openExternal(pagePath)
|
||||
})
|
||||
</code></pre>
|
||||
<h5>Main Process</h5>
|
||||
<pre><code>
|
||||
const {app, dialog} = require('electron')
|
||||
const path = require('path')
|
||||
<p>Open the <a href="https://www.electronjs.org/docs/api/protocol">full protocol API documentation</a> in your
|
||||
browser.</p>
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos')
|
||||
}
|
||||
-----
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
<h3>Demo</h3>
|
||||
<p>
|
||||
First: Launch current page in browser
|
||||
<button id="open-in-browser" class="js-container-target demo-toggle-button">
|
||||
Click to Launch Browser
|
||||
</button>
|
||||
</p>
|
||||
|
||||
</code></pre>
|
||||
<h5>macOS plist</h5>
|
||||
<pre><code>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>electron-api-demos</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Electron API Demos Protocol</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ElectronTeamID</key>
|
||||
<string>VEKTX9H2N7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
require('./renderer.js')
|
||||
</script>
|
||||
</section>
|
||||
<p>
|
||||
Then: Launch the app from a web link!
|
||||
<a href="electron-fiddle://open">Click here to launch the app</a>
|
||||
</p>
|
||||
|
||||
----
|
||||
|
||||
<p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app
|
||||
as the default for <code>electron-fiddle://</code>. The demo button above will launch a page in your default
|
||||
browser with a link. Click that link and it will re-launch this app.</p>
|
||||
|
||||
|
||||
<h3>Packaging</h3>
|
||||
<p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in
|
||||
development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code>
|
||||
for the app is updated to include the new protocol handler. If you're using <code>electron-packager</code> then you
|
||||
can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this
|
||||
app is below:</p>
|
||||
|
||||
<p>
|
||||
<h5>macOS plist</h5>
|
||||
<pre><code>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>electron-api-demos</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Electron API Demos Protocol</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ElectronTeamID</key>
|
||||
<string>VEKTX9H2N7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
</code>
|
||||
</pre>
|
||||
<p>
|
||||
|
||||
<!-- You can also require other files to run in this process -->
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -1,10 +1,39 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, dialog } = require('electron')
|
||||
const { app, BrowserWindow, ipcMain, shell } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
let mainWindow;
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle')
|
||||
}
|
||||
|
||||
const gotTheLock = app.requestSingleInstanceLock()
|
||||
|
||||
if (!gotTheLock) {
|
||||
app.quit()
|
||||
} else {
|
||||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isMinimized()) mainWindow.restore()
|
||||
mainWindow.focus()
|
||||
}
|
||||
})
|
||||
|
||||
// Create mainWindow, load the rest of the app, etc...
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
@@ -12,58 +41,23 @@ function createWindow () {
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos')
|
||||
}
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
// Handle window controls via IPC
|
||||
ipcMain.on('shell:open', () => {
|
||||
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
|
||||
const pagePath = path.join('file://', pageDirectory, 'index.html')
|
||||
shell.openExternal(pagePath)
|
||||
})
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// All of the Node.js APIs are available in the preload process.
|
||||
// It has the same sandbox as a Chrome extension.
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
// Set up context bridge between the renderer process and the main process
|
||||
contextBridge.exposeInMainWorld(
|
||||
'shell',
|
||||
{
|
||||
open: () => ipcRenderer.send('shell:open'),
|
||||
}
|
||||
)
|
||||
@@ -1,14 +1,8 @@
|
||||
const { shell } = require('electron')
|
||||
const path = require('path')
|
||||
// This file is required by the index.html file and will
|
||||
// be executed in the renderer process for that window.
|
||||
// All APIs exposed by the context bridge are available here.
|
||||
|
||||
const openInBrowserButton = document.getElementById('open-in-browser')
|
||||
const openAppLink = document.getElementById('open-app-link')
|
||||
// Hides openAppLink when loaded inside Electron
|
||||
openAppLink.style.display = 'none'
|
||||
|
||||
openInBrowserButton.addEventListener('click', () => {
|
||||
console.log('clicked')
|
||||
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
|
||||
const pagePath = path.join('file://', pageDirectory, 'index.html')
|
||||
shell.openExternal(pagePath)
|
||||
})
|
||||
// Binds the buttons to the context bridge API.
|
||||
document.getElementById('open-in-browser').addEventListener('click', () => {
|
||||
shell.open();
|
||||
});
|
||||
BIN
docs/images/chrome-processes.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
docs/images/connection-status.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 32 KiB |
0
docs/images/versioning-sketch-2.png
Executable file → Normal file
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
@@ -2,15 +2,14 @@
|
||||
|
||||
These are the guidelines for writing Electron documentation.
|
||||
|
||||
## Titles
|
||||
## Headings
|
||||
|
||||
* Each page must have a single `#`-level title at the top.
|
||||
* Chapters in the same page must have `##`-level titles.
|
||||
* Sub-chapters need to increase the number of `#` in the title according to
|
||||
* Chapters in the same page must have `##`-level headings.
|
||||
* Sub-chapters need to increase the number of `#` in the heading according to
|
||||
their nesting depth.
|
||||
* 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.
|
||||
* The page's title must follow [APA title case][title-case].
|
||||
* All chapters must follow [APA sentence case][sentence-case].
|
||||
|
||||
Using `Quick Start` as example:
|
||||
|
||||
@@ -44,12 +43,20 @@ 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).
|
||||
* Lines should be wrapped at 80 columns.
|
||||
* Keep line lengths between 80 and 100 characters if possible for readability
|
||||
purposes.
|
||||
* 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
|
||||
|
||||
@@ -60,14 +67,15 @@ For API references, there are exceptions to this rule.
|
||||
|
||||
The following rules only apply to the documentation of APIs.
|
||||
|
||||
### Page title
|
||||
### Title and description
|
||||
|
||||
Each page must use the actual object name returned by `require('electron')`
|
||||
as the title, such as `BrowserWindow`, `autoUpdater`, and `session`.
|
||||
Each module's API doc must use the actual object name returned by `require('electron')`
|
||||
as its title (such as `BrowserWindow`, `autoUpdater`, and `session`).
|
||||
|
||||
Under the page title must be a one-line description starting with `>`.
|
||||
Directly under the page title, add a one-line description of the module
|
||||
as a markdown quote (beginning with `>`).
|
||||
|
||||
Using `session` as example:
|
||||
Using the `session` module as an example:
|
||||
|
||||
```markdown
|
||||
# session
|
||||
@@ -99,14 +107,19 @@ 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 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.
|
||||
* 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.
|
||||
* 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:
|
||||
|
||||
@@ -142,7 +155,7 @@ Using the `Session` and `Cookies` classes as an example:
|
||||
#### `cookies.get(filter, callback)`
|
||||
```
|
||||
|
||||
### Methods
|
||||
### Methods and their arguments
|
||||
|
||||
The methods chapter must be in the following form:
|
||||
|
||||
@@ -155,8 +168,12 @@ The methods chapter must be in the following form:
|
||||
...
|
||||
```
|
||||
|
||||
The title can be `###` or `####`-levels depending on whether it is a method of
|
||||
a module or a class.
|
||||
#### Heading level
|
||||
|
||||
The heading can be `###` or `####`-levels depending on whether the method
|
||||
belongs to a module or a class.
|
||||
|
||||
#### Function signature
|
||||
|
||||
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
|
||||
@@ -165,23 +182,33 @@ name.
|
||||
For example, the methods of the `Session` class under the `session` module must
|
||||
use `ses` as the `objectName`.
|
||||
|
||||
The optional arguments are notated by square brackets `[]` surrounding the optional argument
|
||||
as well as the comma required if this optional argument follows another
|
||||
Optional arguments are notated by square brackets `[]` surrounding the optional
|
||||
argument as well as the comma required if this optional argument follows another
|
||||
argument:
|
||||
|
||||
```sh
|
||||
```markdown
|
||||
required[, optional]
|
||||
```
|
||||
|
||||
Below the method is more detailed information on each of the arguments. The type
|
||||
of argument is notated by either the common types:
|
||||
#### Argument descriptions
|
||||
|
||||
* [`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)
|
||||
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
|
||||
|
||||
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
|
||||
@@ -191,12 +218,6 @@ 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:
|
||||
@@ -211,8 +232,8 @@ Returns:
|
||||
...
|
||||
```
|
||||
|
||||
The title can be `###` or `####`-levels depending on whether it is an event of
|
||||
a module or a class.
|
||||
The heading can be `###` or `####`-levels depending on whether the event
|
||||
belongs to a module or a class.
|
||||
|
||||
The arguments of an event follow the same rules as methods.
|
||||
|
||||
@@ -226,9 +247,13 @@ The properties chapter must be in following form:
|
||||
...
|
||||
```
|
||||
|
||||
The title can be `###` or `####`-levels depending on whether it is a property of
|
||||
a module or a class.
|
||||
The heading can be `###` or `####`-levels depending on whether the property
|
||||
belongs to 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
|
||||
|
||||
@@ -18,7 +18,7 @@ distributable Electron application, such as bundling your application,
|
||||
rebranding the executable, and setting the right icons.
|
||||
|
||||
You can check the example of how to package your app with `electron-forge` in
|
||||
our [Quick Start Guide](quick-start.md#package-and-distribute-the-application).
|
||||
the [Quick Start guide](quick-start.md#package-and-distribute-your-application).
|
||||
|
||||
## Manual distribution
|
||||
|
||||
|
||||
@@ -88,14 +88,15 @@ without meaning any harm:
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Note that up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
|
||||
as well. However, it should not be used anymore if it can be avoided.
|
||||
|
||||
To see all of this in action, check out Electron Fiddle's source code,
|
||||
[especially its `electron-forge` configuration
|
||||
file](https://github.com/electron/fiddle/blob/master/forge.config.js).
|
||||
@@ -133,7 +134,7 @@ are likely using [`electron-packager`], which includes [`electron-osx-sign`] and
|
||||
|
||||
If you're using Packager's API, you can pass [in configuration that both signs
|
||||
and notarizes your
|
||||
application](https://electron.github.io/electron-packager/master/interfaces/electronpackager.options.html).
|
||||
application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html).
|
||||
|
||||
```js
|
||||
const packager = require('electron-packager')
|
||||
@@ -165,14 +166,15 @@ without meaning any harm:
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
|
||||
as well. However, it should not be used anymore if it can be avoided.
|
||||
|
||||
## Mac App Store
|
||||
|
||||
See the [Mac App Store Guide].
|
||||
|
||||
@@ -47,18 +47,18 @@ of this theming, due to the use of the macOS 10.14 SDK.
|
||||
|
||||
## Example
|
||||
|
||||
We'll start with a working application from the
|
||||
[Quick Start Guide](quick-start.md) and add functionality gradually.
|
||||
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.
|
||||
|
||||
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".
|
||||
```javascript fiddle='docs/fiddles/features/macos-dark-mode'
|
||||
|
||||
Add the following lines to the `index.html` file:
|
||||
```
|
||||
|
||||
```html
|
||||
### How does this work?
|
||||
|
||||
Starting with the `index.html` file:
|
||||
|
||||
```html title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
@@ -80,65 +80,70 @@ Add the following lines to the `index.html` file:
|
||||
</html>
|
||||
```
|
||||
|
||||
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:
|
||||
And the `style.css` file:
|
||||
|
||||
* 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`.
|
||||
```css title='style.css'
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body { background: #333; color: white; }
|
||||
}
|
||||
|
||||
To add listeners and handlers, add the following lines to the `renderer.js` file:
|
||||
@media (prefers-color-scheme: light) {
|
||||
body { background: #ddd; color: black; }
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
const { ipcRenderer } = require('electron')
|
||||
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.
|
||||
|
||||
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 ipcRenderer.invoke('dark-mode:toggle')
|
||||
const isDarkMode = await window.darkMode.toggle()
|
||||
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
|
||||
})
|
||||
|
||||
document.getElementById('reset-to-system').addEventListener('click', async () => {
|
||||
await ipcRenderer.invoke('dark-mode:system')
|
||||
await window.darkMode.system()
|
||||
document.getElementById('theme-source').innerHTML = 'System'
|
||||
})
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
Finally, the `main.js` file represents the main process and contains the actual `nativeTheme` API.
|
||||
|
||||
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
|
||||
```js
|
||||
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -158,45 +163,43 @@ function createWindow () {
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
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 `ipcMain.handle` methods are how the main process responds to the click events from the buttons
|
||||
on the HTML page.
|
||||
|
||||
Create a `styles.css` file and add the following lines:
|
||||
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.
|
||||
|
||||
```css fiddle='docs/fiddles/features/macos-dark-mode'
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body { background: #333; color: white; }
|
||||
}
|
||||
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.
|
||||
|
||||
@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:
|
||||
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.
|
||||
|
||||

|
||||
|
||||
[system-wide-dark-mode]: https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/dark-mode/
|
||||
[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
|
||||
[prefer-color-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
|
||||
[packager-darwindarkmode-api]: https://electron.github.io/electron-packager/main/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
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
# Desktop Environment Integration
|
||||
|
||||
Different operating systems provide different features for integrating desktop
|
||||
applications into their desktop environments. For example, on Windows,
|
||||
applications can put shortcuts in the JumpList of task bar, and on Mac,
|
||||
applications can put a custom menu in the dock menu.
|
||||
|
||||
This guide explains how to integrate your application into those desktop
|
||||
environments with Electron APIs.
|
||||
|
||||
## Notifications
|
||||
|
||||
See the [Notifications documentation](notifications.md).
|
||||
|
||||
## Recent Documents
|
||||
|
||||
See [Recent Documents documentation](recent-documents.md).
|
||||
|
||||
## Progress Bar
|
||||
|
||||
See the [Progress Bar documentation](progress-bar.md).
|
||||
|
||||
## Unity Launcher
|
||||
|
||||
See the [Unity Launcher documentation][unity-launcher].
|
||||
|
||||
## Represented File for macOS Window
|
||||
|
||||
See the [Represented File documentation](represented-file.md).
|
||||
|
||||
## Dragging files out of the window
|
||||
|
||||
See the [Native File Drag & Drop documentation](native-file-drag-drop.md).
|
||||
|
||||
[unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher
|
||||
@@ -1,22 +1,27 @@
|
||||
# Electron Release Timelines
|
||||
|
||||
Special notes:
|
||||
|
||||
* The `-beta.1` and `stable` dates are our solid release dates.
|
||||
* We strive for weekly beta releases, however we often release more betas than scheduled.
|
||||
* All dates are our goals but there may be reasons for adjusting the stable deadline, such as security bugs.
|
||||
* Take a look at the [5.0.0 Timeline blog post](https://electronjs.org/blog/electron-5-0-timeline) for info about publicizing our release dates.
|
||||
* Since Electron 6.0, we've been targeting every other Chromium version and releasing our stable on the same day as Chrome stable. You can reference Chromium's release schedule [here](https://chromiumdash.appspot.com/schedule). See [Electron's new release cadence blog post](https://www.electronjs.org/blog/12-week-cadence) for more details on our release schedule.
|
||||
* Electron 15.0 only will include a special Alpha release. Starting in Electron 16.0, we will release on an 8-week cadence. See [Electron's new 8-week cadence blog post](https://www.electronjs.org/blog/8-week-cadence) for more details.
|
||||
|
||||
| Version | -beta.1 | Stable | Chrome | Node |
|
||||
| ------- | ------- | ------ | ------ | ---- |
|
||||
| 2.0.0 | 2018-02-21 | 2018-05-01 | M61 | v8.9 |
|
||||
| 3.0.0 | 2018-06-21 | 2018-09-18 | M66 | v10.2 |
|
||||
| 4.0.0 | 2018-10-11 | 2018-12-20 | M69 | v10.11 |
|
||||
| 5.0.0 | 2019-01-22 | 2019-04-24 | M73 | v12.0 |
|
||||
| 6.0.0 | 2019-05-01 | 2019-07-30 | M76 | v12.4 |
|
||||
| 7.0.0 | 2019-08-01 | 2019-10-22 | M78 | v12.8 |
|
||||
| 8.0.0 | 2019-10-24 | 2020-02-04 | M80 | v12.13 |
|
||||
| 9.0.0 | 2020-02-06 | 2020-05-19 | M83 | v12.14 |
|
||||
| 10.0.0 | 2020-05-21 | 2020-08-25 | M85 | v12.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 |
|
||||
| Electron | Alpha | Beta | Stable | Chrome | Node |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- |
|
||||
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | M61 | v8.9 |
|
||||
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | M66 | v10.2 |
|
||||
| 4.0.0 | -- | 2018-Oct-11 | 2018-Dec-20 | M69 | v10.11 |
|
||||
| 5.0.0 | -- | 2019-Jan-22 | 2019-Apr-24 | M73 | v12.0 |
|
||||
| 6.0.0 | -- | 2019-May-01 | 2019-Jul-30 | M76 | v12.4 |
|
||||
| 7.0.0 | -- | 2019-Aug-01 | 2019-Oct-22 | M78 | v12.8 |
|
||||
| 8.0.0 | -- | 2019-Oct-24 | 2020-Feb-04 | M80 | v12.13 |
|
||||
| 9.0.0 | -- | 2020-Feb-06 | 2020-May-19 | M83 | v12.14 |
|
||||
| 10.0.0 | -- | 2020-May-21 | 2020-Aug-25 | M85 | v12.16 |
|
||||
| 11.0.0 | -- | 2020-Aug-27 | 2020-Nov-17 | M87 | v12.18 |
|
||||
| 12.0.0 | -- | 2020-Nov-19 | 2021-Mar-02 | M89 | v14.16 |
|
||||
| 13.0.0 | -- | 2021-Mar-04 | 2021-May-25 | M91 | v14.16 |
|
||||
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | M93 | TBD |
|
||||
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | M94 | TBD |
|
||||
|
||||
@@ -51,4 +51,4 @@ Somewhere in the Electron binary there will be a sequence of bytes that look lik
|
||||
|
||||
To flip a fuse you find its position in the fuse wire and change it to "0" or "1" depending on the state you'd like.
|
||||
|
||||
You can view the current schema [here](https://github.com/electron/electron/blob/master/build/fuses/fuses.json).
|
||||
You can view the current schema [here](https://github.com/electron/electron/blob/master/build/fuses/fuses.json5).
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# In-App Purchase (macOS)
|
||||
# In-App Purchases (macOS)
|
||||
|
||||
## Preparing
|
||||
|
||||
|
||||