mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
156 Commits
gha
...
same-party
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3bd73cbd7 | ||
|
|
4f3391d92a | ||
|
|
5cbaf97e31 | ||
|
|
2d9c5a62c6 | ||
|
|
23f690ffd0 | ||
|
|
8f4e94694e | ||
|
|
af47434dc8 | ||
|
|
8ab99e2d8e | ||
|
|
ffcccdcf37 | ||
|
|
ce2ac1c0c2 | ||
|
|
1c3feddef8 | ||
|
|
c779f19ee5 | ||
|
|
09fbee9998 | ||
|
|
69d371fc41 | ||
|
|
b6db80c1c4 | ||
|
|
b87cf56b09 | ||
|
|
bc40a1aa0c | ||
|
|
d8606efe94 | ||
|
|
523e0d4574 | ||
|
|
3b23911121 | ||
|
|
516cbfa29a | ||
|
|
5c71377f40 | ||
|
|
85db55516b | ||
|
|
e071faa31b | ||
|
|
53e1c63d69 | ||
|
|
b8917a03d6 | ||
|
|
b33bc21159 | ||
|
|
9bb821a818 | ||
|
|
432b89445f | ||
|
|
00a3c3c883 | ||
|
|
288ec2ed93 | ||
|
|
90ca228cdc | ||
|
|
aa4ea630f8 | ||
|
|
d6fedc20bc | ||
|
|
42a72df1e7 | ||
|
|
16764199a7 | ||
|
|
4113f9d6a6 | ||
|
|
7aff4bc1dd | ||
|
|
d5b0df6775 | ||
|
|
b4f66e5f79 | ||
|
|
fbab31a699 | ||
|
|
7bccdbcbdb | ||
|
|
d715090a36 | ||
|
|
31054d6d46 | ||
|
|
76859affbd | ||
|
|
f3224365cf | ||
|
|
4a24337b14 | ||
|
|
2312420deb | ||
|
|
a05c9bcfb9 | ||
|
|
25f52d5d32 | ||
|
|
1fefe25ed5 | ||
|
|
d92ffceafb | ||
|
|
6e1dc452f9 | ||
|
|
9daf416097 | ||
|
|
738e0b9664 | ||
|
|
370a2c702b | ||
|
|
3f85bd57a2 | ||
|
|
5c8b5ff811 | ||
|
|
7d7f390c93 | ||
|
|
0fc5e42018 | ||
|
|
1ff780d3dd | ||
|
|
dd142b0327 | ||
|
|
0df4312ded | ||
|
|
95e3df589f | ||
|
|
7441b812e4 | ||
|
|
12f4204824 | ||
|
|
b84beed666 | ||
|
|
ebeb8adaf4 | ||
|
|
d5433ec0cc | ||
|
|
8d49957c93 | ||
|
|
471c44c709 | ||
|
|
8f4e7bde5e | ||
|
|
94fdb02987 | ||
|
|
2377746413 | ||
|
|
2bb2ef92da | ||
|
|
c994eb8e13 | ||
|
|
a9d358e730 | ||
|
|
69e30e8d67 | ||
|
|
02dfdce54a | ||
|
|
bd304f7c9d | ||
|
|
c2524d762b | ||
|
|
0b1e1b1612 | ||
|
|
0d0340ec69 | ||
|
|
f0d42aed88 | ||
|
|
ddb1c784d0 | ||
|
|
33ae7cc786 | ||
|
|
cbd1b4486c | ||
|
|
40a13b649f | ||
|
|
5728d3b709 | ||
|
|
0778cc70bb | ||
|
|
f0c02568da | ||
|
|
3c01b58114 | ||
|
|
c257cc25a2 | ||
|
|
e1ec17d641 | ||
|
|
ce7e0afd0a | ||
|
|
f589b73dee | ||
|
|
44f29fc675 | ||
|
|
daf00de2ed | ||
|
|
877a3b9fe2 | ||
|
|
0bcaaca6bd | ||
|
|
8619bd5027 | ||
|
|
4875c9b645 | ||
|
|
f4979e3cd2 | ||
|
|
d6a80bad05 | ||
|
|
cb0da6ff34 | ||
|
|
9aa73abe78 | ||
|
|
85bc005cd6 | ||
|
|
ee8d97d7fe | ||
|
|
3a510a26d0 | ||
|
|
9afeaa3a4c | ||
|
|
10a165a9ff | ||
|
|
66b4b21646 | ||
|
|
6f14dba7a0 | ||
|
|
3609fc7402 | ||
|
|
344b7f0d06 | ||
|
|
96f5f89f1b | ||
|
|
9c94fd7afb | ||
|
|
39ee94089a | ||
|
|
b2fcc15ec7 | ||
|
|
763bc62c7f | ||
|
|
abb71f5307 | ||
|
|
c12ab7c941 | ||
|
|
5c7579ab1c | ||
|
|
f0f027c06d | ||
|
|
58a21a3cd9 | ||
|
|
79e714a825 | ||
|
|
44e055a788 | ||
|
|
e78ce82641 | ||
|
|
1574cbf137 | ||
|
|
3340bc1bf9 | ||
|
|
2029224a84 | ||
|
|
f3676ff975 | ||
|
|
0b5fceb50e | ||
|
|
dbe170c665 | ||
|
|
3d2a754531 | ||
|
|
d6bb9b40b0 | ||
|
|
2c03b8fd6b | ||
|
|
67894f1493 | ||
|
|
471449d9f6 | ||
|
|
dec96acf14 | ||
|
|
d2b07a484d | ||
|
|
371bca69b6 | ||
|
|
088affd4a4 | ||
|
|
0e4e9dc98c | ||
|
|
b639fa4626 | ||
|
|
7981d955b8 | ||
|
|
cf5f0419f1 | ||
|
|
262723e394 | ||
|
|
6697042c0a | ||
|
|
2677f36db1 | ||
|
|
d504d150ef | ||
|
|
0f68d845f9 | ||
|
|
1ba535296e | ||
|
|
e8d9294d9d | ||
|
|
b55d7f4a16 | ||
|
|
7999ea39e2 |
@@ -80,12 +80,14 @@ executors:
|
||||
machine: true
|
||||
|
||||
linux-arm:
|
||||
resource_class: electronjs/linux-arm
|
||||
machine: true
|
||||
resource_class: electronjs/aks-linux-arm-test
|
||||
docker:
|
||||
- image: ghcr.io/electron/test:arm32v7-8e0f85b708fa58e28e4824954d6fd55adfda5e9e
|
||||
|
||||
linux-arm64:
|
||||
resource_class: electronjs/linux-arm64
|
||||
machine: true
|
||||
resource_class: electronjs/aks-linux-arm-test
|
||||
docker:
|
||||
- image: ghcr.io/electron/test:arm64v8-76d5d29e247972da3855a01c2d8cf72c5998233a
|
||||
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "SLACK_WEBHOOK" Slack hook URL to send notifications.
|
||||
@@ -335,46 +337,27 @@ step-setup-env-for-build: &step-setup-env-for-build
|
||||
# To find `gn` executable.
|
||||
echo 'export CHROMIUM_BUILDTOOLS_PATH="'"$PWD"'/src/buildtools"' >> $BASH_ENV
|
||||
|
||||
step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
step-setup-rbe-for-build: &step-setup-rbe-for-build
|
||||
run:
|
||||
name: Setup Goma
|
||||
name: Setup RBE
|
||||
command: |
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=200' >> $BASH_ENV
|
||||
echo 'ulimit -n 10000' >> $BASH_ENV
|
||||
echo 'sudo launchctl limit maxfiles 65536 200000' >> $BASH_ENV
|
||||
fi
|
||||
if [ ! -z "$RAW_GOMA_AUTH" ]; then
|
||||
echo $RAW_GOMA_AUTH > ~/.goma_oauth2_config
|
||||
fi
|
||||
git clone https://github.com/electron/build-tools.git
|
||||
cd build-tools
|
||||
npm install
|
||||
npx yarn --ignore-engines
|
||||
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
|
||||
if [ ! -z "$RAW_GOMA_AUTH" ] && [ "`third_party/goma/goma_auth.py info`" != "Login as Fermi Planck" ]; then
|
||||
echo "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token."
|
||||
exit 1
|
||||
fi
|
||||
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
|
||||
echo 'export GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
|
||||
echo 'export GOMA_FALLBACK_ON_AUTH_FAILURE=true' >> $BASH_ENV
|
||||
cd ..
|
||||
touch "${TMPDIR:=/tmp}"/.goma-ready
|
||||
background: true
|
||||
|
||||
step-wait-for-goma: &step-wait-for-goma
|
||||
run:
|
||||
name: Wait for Goma
|
||||
command: |
|
||||
until [ -f "${TMPDIR:=/tmp}"/.goma-ready ]
|
||||
do
|
||||
sleep 5
|
||||
done
|
||||
echo "Goma ready"
|
||||
no_output_timeout: 5m
|
||||
# Pull down credential helper and print status
|
||||
node -e "require('./src/utils/reclient.js').downloadAndPrepare({})"
|
||||
HELPER=$(node -p "require('./src/utils/reclient.js').helperPath({})")
|
||||
$HELPER login
|
||||
echo 'export RBE_service='`node -e "console.log(require('./src/utils/reclient.js').serviceAddress)"` >> $BASH_ENV
|
||||
echo 'export RBE_experimental_credentials_helper='`node -e "console.log(require('./src/utils/reclient.js').helperPath({}))"` >> $BASH_ENV
|
||||
echo 'export RBE_experimental_credentials_helper_args="print"' >> $BASH_ENV
|
||||
|
||||
step-restore-brew-cache: &step-restore-brew-cache
|
||||
restore_cache:
|
||||
@@ -548,6 +531,13 @@ step-fix-sync: &step-fix-sync
|
||||
sed -i '' "s/Updating depot_tools... //g" gn_ensure_file
|
||||
cipd ensure --root src/buildtools/mac -ensure-file gn_ensure_file
|
||||
|
||||
# Fix reclient (wrong binary)
|
||||
echo 'infra/rbe/client/${platform}' `gclient getdep --deps-file=src/DEPS -r 'src/buildtools/reclient:infra/rbe/client/${platform}'` > gn_ensure_file
|
||||
# Remove extra output from calling gclient getdep which always calls update_depot_tools
|
||||
sed -i '' "s/Updating depot_tools... //g" gn_ensure_file
|
||||
cipd ensure --root src/buildtools/reclient -ensure-file gn_ensure_file
|
||||
python3 src/buildtools/reclient_cfgs/configure_reclient_cfgs.py --rbe_instance "projects/rbe-chrome-untrusted/instances/default_instance" --reproxy_cfg_template reproxy.cfg.template --rewrapper_cfg_project "" --skip_remoteexec_cfg_fetch
|
||||
|
||||
# Fix dsymutil (wrong binary)
|
||||
if [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
export DSYM_SHA_FILE=src/tools/clang/dsymutil/bin/dsymutil.arm64.sha1
|
||||
@@ -600,7 +590,7 @@ step-gn-gen-default: &step-gn-gen-default
|
||||
name: Default GN gen
|
||||
command: |
|
||||
cd src
|
||||
gn gen out/Default --args="import(\"$GN_CONFIG\") import(\"$GN_GOMA_FILE\") $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
gn gen out/Default --args="import(\"$GN_CONFIG\") use_remoteexec=true $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
|
||||
step-gn-check: &step-gn-check
|
||||
run:
|
||||
@@ -636,16 +626,16 @@ step-electron-chromedriver-build: &step-electron-chromedriver-build
|
||||
command: |
|
||||
cd src
|
||||
if [ "`uname`" != "Darwin" ] && ([ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]); then
|
||||
gn gen out/chromedriver --args="import(\"$GN_CONFIG\") import(\"$GN_GOMA_FILE\") is_component_ffmpeg=false proprietary_codecs=false $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
gn gen out/chromedriver --args="import(\"$GN_CONFIG\") use_remoteexec=true is_component_ffmpeg=false proprietary_codecs=false $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
export CHROMEDRIVER_DIR="out/chromedriver"
|
||||
else
|
||||
export CHROMEDRIVER_DIR="out/Default"
|
||||
fi
|
||||
ninja -C $CHROMEDRIVER_DIR electron:electron_chromedriver -j $NUMBER_OF_NINJA_PROCESSES
|
||||
autoninja -C $CHROMEDRIVER_DIR electron:electron_chromedriver -j $NUMBER_OF_NINJA_PROCESSES
|
||||
if [ "`uname`" == "Linux" ]; then
|
||||
electron/script/strip-binaries.py --target-cpu="$TARGET_ARCH" --file $PWD/$CHROMEDRIVER_DIR/chromedriver
|
||||
fi
|
||||
ninja -C $CHROMEDRIVER_DIR electron:electron_chromedriver_zip
|
||||
autoninja -C $CHROMEDRIVER_DIR electron:electron_chromedriver_zip
|
||||
if [ "`uname`" != "Darwin" ] && ([ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]); then
|
||||
cp out/chromedriver/chromedriver.zip out/Default
|
||||
fi
|
||||
@@ -655,7 +645,7 @@ step-nodejs-headers-build: &step-nodejs-headers-build
|
||||
name: Build Node.js headers
|
||||
command: |
|
||||
cd src
|
||||
ninja -C out/Default electron:node_headers
|
||||
autoninja -C out/Default electron:node_headers
|
||||
|
||||
step-electron-publish: &step-electron-publish
|
||||
run:
|
||||
@@ -709,14 +699,14 @@ step-ffmpeg-gn-gen: &step-ffmpeg-gn-gen
|
||||
name: ffmpeg GN gen
|
||||
command: |
|
||||
cd src
|
||||
gn gen out/ffmpeg --args="import(\"//electron/build/args/ffmpeg.gn\") import(\"$GN_GOMA_FILE\") $GN_EXTRA_ARGS"
|
||||
gn gen out/ffmpeg --args="import(\"//electron/build/args/ffmpeg.gn\") use_remoteexec=true $GN_EXTRA_ARGS"
|
||||
|
||||
step-ffmpeg-build: &step-ffmpeg-build
|
||||
run:
|
||||
name: Non proprietary ffmpeg build
|
||||
command: |
|
||||
cd src
|
||||
ninja -C out/ffmpeg electron:electron_ffmpeg_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
autoninja -C out/ffmpeg electron:electron_ffmpeg_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
|
||||
step-verify-mksnapshot: &step-verify-mksnapshot
|
||||
run:
|
||||
@@ -748,26 +738,13 @@ step-setup-linux-for-headless-testing: &step-setup-linux-for-headless-testing
|
||||
sh -e /etc/init.d/xvfb start
|
||||
fi
|
||||
|
||||
step-show-goma-stats: &step-show-goma-stats
|
||||
run:
|
||||
shell: /bin/bash
|
||||
name: Check goma stats after build
|
||||
command: |
|
||||
set +e
|
||||
set +o pipefail
|
||||
python3 $GOMA_DIR/goma_ctl.py stat
|
||||
python3 $GOMA_DIR/diagnose_goma_log.py
|
||||
true
|
||||
when: always
|
||||
background: true
|
||||
|
||||
step-mksnapshot-build: &step-mksnapshot-build
|
||||
run:
|
||||
name: mksnapshot build
|
||||
no_output_timeout: 30m
|
||||
command: |
|
||||
cd src
|
||||
ninja -C out/Default electron:electron_mksnapshot -j $NUMBER_OF_NINJA_PROCESSES
|
||||
autoninja -C out/Default electron:electron_mksnapshot -j $NUMBER_OF_NINJA_PROCESSES
|
||||
gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
SEDOPTION="-i"
|
||||
@@ -790,7 +767,7 @@ step-mksnapshot-build: &step-mksnapshot-build
|
||||
fi
|
||||
fi
|
||||
if [ "$SKIP_DIST_ZIP" != "1" ]; then
|
||||
ninja -C out/Default electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
autoninja -C out/Default electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
(cd out/Default; zip mksnapshot.zip mksnapshot_args gen/v8/embedded.S)
|
||||
fi
|
||||
|
||||
@@ -800,7 +777,7 @@ step-hunspell-build: &step-hunspell-build
|
||||
command: |
|
||||
cd src
|
||||
if [ "$SKIP_DIST_ZIP" != "1" ]; then
|
||||
ninja -C out/Default electron:hunspell_dictionaries_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
autoninja -C out/Default electron:hunspell_dictionaries_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
fi
|
||||
|
||||
step-maybe-generate-libcxx: &step-maybe-generate-libcxx
|
||||
@@ -809,9 +786,9 @@ step-maybe-generate-libcxx: &step-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
|
||||
autoninja -C out/Default electron:libcxx_headers_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
autoninja -C out/Default electron:libcxxabi_headers_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
autoninja -C out/Default electron:libcxx_objects_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
fi
|
||||
|
||||
step-maybe-generate-breakpad-symbols: &step-maybe-generate-breakpad-symbols
|
||||
@@ -821,7 +798,7 @@ step-maybe-generate-breakpad-symbols: &step-maybe-generate-breakpad-symbols
|
||||
command: |
|
||||
if [ "$GENERATE_SYMBOLS" == "true" ]; then
|
||||
cd src
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
autoninja -C out/Default electron:electron_symbols
|
||||
fi
|
||||
|
||||
step-maybe-zip-symbols: &step-maybe-zip-symbols
|
||||
@@ -830,8 +807,8 @@ step-maybe-zip-symbols: &step-maybe-zip-symbols
|
||||
command: |
|
||||
cd src
|
||||
export BUILD_PATH="$PWD/out/Default"
|
||||
ninja -C out/Default electron:licenses
|
||||
ninja -C out/Default electron:electron_version_file
|
||||
autoninja -C out/Default electron:licenses
|
||||
autoninja -C out/Default electron:electron_version_file
|
||||
electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
|
||||
step-maybe-zip-symbols-and-clean: &step-maybe-zip-symbols-and-clean
|
||||
@@ -840,8 +817,8 @@ step-maybe-zip-symbols-and-clean: &step-maybe-zip-symbols-and-clean
|
||||
command: |
|
||||
cd src
|
||||
export BUILD_PATH="$PWD/out/Default"
|
||||
ninja -C out/Default electron:licenses
|
||||
ninja -C out/Default electron:electron_version_file
|
||||
autoninja -C out/Default electron:licenses
|
||||
autoninja -C out/Default electron:electron_version_file
|
||||
DELETE_DSYMS_AFTER_ZIP=1 electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
|
||||
step-maybe-cross-arch-snapshot: &step-maybe-cross-arch-snapshot
|
||||
@@ -1188,11 +1165,10 @@ commands:
|
||||
could-be-aks:
|
||||
type: boolean
|
||||
steps:
|
||||
- *step-setup-goma-for-build
|
||||
- *step-setup-rbe-for-build
|
||||
- checkout-from-cache:
|
||||
could-be-aks: << parameters.could-be-aks >>
|
||||
- *step-setup-env-for-build
|
||||
- *step-wait-for-goma
|
||||
- *step-gn-gen-default
|
||||
- *step-gn-check
|
||||
build_and_save_artifacts:
|
||||
@@ -1213,8 +1189,6 @@ commands:
|
||||
- step-electron-dist-build:
|
||||
additional-targets: electron:node_headers third_party/electron_node:overlapped-checker electron:hunspell_dictionaries_zip
|
||||
|
||||
- *step-show-goma-stats
|
||||
|
||||
# mksnapshot
|
||||
- *step-mksnapshot-build
|
||||
- *step-maybe-cross-arch-snapshot
|
||||
@@ -1343,7 +1317,7 @@ commands:
|
||||
command: |
|
||||
cd src
|
||||
if [ "$SKIP_DIST_ZIP" != "1" ]; then
|
||||
ninja -C out/Default electron:electron_dist_zip << parameters.additional-targets >> -j $NUMBER_OF_NINJA_PROCESSES
|
||||
autoninja -C out/Default electron:electron_dist_zip << parameters.additional-targets >> -j $NUMBER_OF_NINJA_PROCESSES
|
||||
if [ "$CHECK_DIST_MANIFEST" == "1" ]; then
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
target_os=mac
|
||||
@@ -1444,7 +1418,7 @@ commands:
|
||||
- when:
|
||||
condition: << parameters.build >>
|
||||
steps:
|
||||
- *step-setup-goma-for-build
|
||||
- *step-setup-rbe-for-build
|
||||
- when:
|
||||
condition: << parameters.checkout-and-assume-cache >>
|
||||
steps:
|
||||
@@ -1563,7 +1537,6 @@ commands:
|
||||
steps:
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-setup-env-for-build
|
||||
- *step-wait-for-goma
|
||||
- *step-get-more-space-on-mac
|
||||
- *step-fix-sync
|
||||
- *step-delete-git-directories
|
||||
@@ -1657,17 +1630,15 @@ commands:
|
||||
export LLVM_SYMBOLIZER_PATH=$PWD/third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer
|
||||
export MOCHA_TIMEOUT=180000
|
||||
echo "Piping output to ASAN_SYMBOLIZE ($ASAN_SYMBOLIZE)"
|
||||
(cd electron && (circleci tests glob "spec/*-spec.ts" | circleci tests run --command="xargs node script/yarn test --runners=main --trace-uncaught --enable-logging --files" --split-by=timings 2>&1)) | $ASAN_SYMBOLIZE
|
||||
(cd electron && (circleci tests glob "spec/*-spec.ts" | xargs -I@ -P4 bash -c "echo $(pwd)/@" | circleci tests run --command="xargs node script/yarn test --runners=main --trace-uncaught --enable-logging --files" --split-by=timings 2>&1)) | $ASAN_SYMBOLIZE
|
||||
else
|
||||
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)
|
||||
else
|
||||
if [ "$TARGET_ARCH" == "ia32" ]; then
|
||||
npm_config_arch=x64 node electron/node_modules/dugite/script/download-git.js
|
||||
fi
|
||||
(cd electron && (circleci tests glob "spec/*-spec.ts" | circleci tests run --command="xargs node script/yarn test --runners=main --trace-uncaught --enable-logging --files" --split-by=timings))
|
||||
fi
|
||||
if [ "$TARGET_ARCH" == "ia32" ]; then
|
||||
npm_config_arch=x64 node electron/node_modules/dugite/script/download-git.js
|
||||
fi
|
||||
(cd electron && (circleci tests glob "spec/*-spec.ts" | xargs -I@ -P4 bash -c "echo $(pwd)/@" | circleci tests run --command="xargs node script/yarn test --runners=main --trace-uncaught --enable-logging --files" --split-by=timings))
|
||||
fi
|
||||
- store_test_results:
|
||||
path: src/junit
|
||||
@@ -1751,14 +1722,12 @@ commands:
|
||||
- *step-fix-sync
|
||||
- *step-setup-env-for-build
|
||||
- *step-fix-known-hosts-linux
|
||||
- *step-setup-goma-for-build
|
||||
- *step-wait-for-goma
|
||||
- *step-setup-rbe-for-build
|
||||
- *step-gn-gen-default
|
||||
|
||||
# Electron app
|
||||
- ninja_build_electron:
|
||||
build-type: << parameters.build-type >>
|
||||
- *step-show-goma-stats
|
||||
- *step-maybe-generate-breakpad-symbols
|
||||
- *step-maybe-electron-dist-strip
|
||||
- step-electron-dist-build
|
||||
@@ -2165,7 +2134,7 @@ jobs:
|
||||
<<: *env-ninja-status
|
||||
<<: *env-macos-build
|
||||
<<: *env-apple-silicon
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac --custom-var=host_cpu=arm64'
|
||||
steps:
|
||||
- electron-build:
|
||||
persist: true
|
||||
@@ -2297,6 +2266,7 @@ jobs:
|
||||
<<: *env-global
|
||||
<<: *env-headless-testing
|
||||
<<: *env-stack-dumping
|
||||
parallelism: 3
|
||||
steps:
|
||||
- electron-tests:
|
||||
artifact-key: linux-arm
|
||||
@@ -2308,6 +2278,7 @@ jobs:
|
||||
<<: *env-global
|
||||
<<: *env-headless-testing
|
||||
<<: *env-stack-dumping
|
||||
parallelism: 3
|
||||
steps:
|
||||
- electron-tests:
|
||||
artifact-key: linux-arm64
|
||||
|
||||
35
.github/workflows/branch-created.yml
vendored
35
.github/workflows/branch-created.yml
vendored
@@ -8,7 +8,7 @@ permissions: {}
|
||||
jobs:
|
||||
release-branch-created:
|
||||
name: Release Branch Created
|
||||
if: ${{ github.event.ref_type == 'branch' && endsWith(github.event.ref, '-x-y') }}
|
||||
if: ${{ github.event.ref_type == 'branch' && endsWith(github.event.ref, '-x-y') && !startsWith(github.event.ref, 'roller') }}
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
@@ -72,21 +72,44 @@ jobs:
|
||||
with:
|
||||
script: |
|
||||
const major = ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
const nextMajor = major + 1
|
||||
const prevMajor = major - 1
|
||||
|
||||
core.setOutput("major", major)
|
||||
core.setOutput("next-major", nextMajor)
|
||||
core.setOutput("prev-major", prevMajor)
|
||||
core.setOutput("prev-prev-major", prevMajor - 1)
|
||||
core.setOutput("template-view", JSON.stringify({
|
||||
major,
|
||||
"next-major": major + 1,
|
||||
"prev-major": major - 1,
|
||||
"next-major": nextMajor,
|
||||
"prev-major": prevMajor,
|
||||
}))
|
||||
core.setOutput("title", `${major}-x-y`)
|
||||
- name: Create Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/copy-project@a24415515fa60a22f71f9d9d00e36ca82660cde9 # v1.0.1
|
||||
uses: dsanders11/project-actions/copy-project@3a81985616963f32fae17d1d1b406c631f3201a1 # v1.1.0
|
||||
id: create-release-board
|
||||
with:
|
||||
drafts: true
|
||||
project-number: 64
|
||||
# TODO - Set to public once GitHub fixes their GraphQL bug
|
||||
# public: true
|
||||
link-to-repository: electron/electron
|
||||
template-view: ${{ steps.generate-project-metadata.outputs.template-view }}
|
||||
title: ${{ steps.generate-project-metadata.outputs.title}}
|
||||
title: ${{ steps.generate-project-metadata.outputs.major }}-x-y
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
- name: Dump Release Project Board Contents
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
run: gh project item-list ${{ steps.create-release-board.outputs.number }} --owner electron --format json | jq
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
- name: Find Previous Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/find-project@3a81985616963f32fae17d1d1b406c631f3201a1 # v1.1.0
|
||||
id: find-prev-release-board
|
||||
with:
|
||||
title: ${{ steps.generate-project-metadata.outputs.prev-prev-major }}-x-y
|
||||
- name: Close Previous Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/close-project@3a81985616963f32fae17d1d1b406c631f3201a1 # v1.1.0
|
||||
with:
|
||||
project-number: ${{ steps.find-prev-release-board.outputs.number }}
|
||||
|
||||
19
.github/workflows/pull-request-labeled.yml
vendored
19
.github/workflows/pull-request-labeled.yml
vendored
@@ -1,13 +1,26 @@
|
||||
name: Pull Request Labeled
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
types: [labeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
pull-request-labeled-backport-requested:
|
||||
name: backport/requested label added
|
||||
if: github.event.label.name == 'backport/requested 🗳'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger Slack workflow
|
||||
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
"url": "${{ github.event.pull_request.html_url }}"
|
||||
}
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.BACKPORT_REQUESTED_SLACK_WEBHOOK_URL }}
|
||||
pull-request-labeled-deprecation-review-complete:
|
||||
name: deprecation-review/complete label added
|
||||
if: github.event.label.name == 'deprecation-review/complete ✅'
|
||||
|
||||
37
BUILD.gn
37
BUILD.gn
@@ -29,6 +29,7 @@ import("filenames.gni")
|
||||
import("filenames.hunspell.gni")
|
||||
import("filenames.libcxx.gni")
|
||||
import("filenames.libcxxabi.gni")
|
||||
import("js2c_toolchain.gni")
|
||||
|
||||
if (is_mac) {
|
||||
import("//build/config/mac/rules.gni")
|
||||
@@ -165,15 +166,6 @@ npm_action("build_electron_definitions") {
|
||||
outputs = [ "$target_gen_dir/tsc/typings/electron.d.ts" ]
|
||||
}
|
||||
|
||||
webpack_build("electron_asar_bundle") {
|
||||
deps = [ ":build_electron_definitions" ]
|
||||
|
||||
inputs = auto_filenames.asar_bundle_deps
|
||||
|
||||
config_file = "//electron/build/webpack/webpack.config.asar.js"
|
||||
out_file = "$target_gen_dir/js2c/asar_bundle.js"
|
||||
}
|
||||
|
||||
webpack_build("electron_browser_bundle") {
|
||||
deps = [ ":build_electron_definitions" ]
|
||||
|
||||
@@ -219,6 +211,15 @@ webpack_build("electron_isolated_renderer_bundle") {
|
||||
out_file = "$target_gen_dir/js2c/isolated_bundle.js"
|
||||
}
|
||||
|
||||
webpack_build("electron_node_bundle") {
|
||||
deps = [ ":build_electron_definitions" ]
|
||||
|
||||
inputs = auto_filenames.node_bundle_deps
|
||||
|
||||
config_file = "//electron/build/webpack/webpack.config.node.js"
|
||||
out_file = "$target_gen_dir/js2c/node_init.js"
|
||||
}
|
||||
|
||||
webpack_build("electron_utility_bundle") {
|
||||
deps = [ ":build_electron_definitions" ]
|
||||
|
||||
@@ -230,32 +231,37 @@ webpack_build("electron_utility_bundle") {
|
||||
|
||||
action("electron_js2c") {
|
||||
deps = [
|
||||
":electron_asar_bundle",
|
||||
":electron_browser_bundle",
|
||||
":electron_isolated_renderer_bundle",
|
||||
":electron_node_bundle",
|
||||
":electron_renderer_bundle",
|
||||
":electron_sandboxed_renderer_bundle",
|
||||
":electron_utility_bundle",
|
||||
":electron_worker_bundle",
|
||||
"//third_party/electron_node:node_js2c($electron_js2c_toolchain)",
|
||||
]
|
||||
|
||||
sources = [
|
||||
"$target_gen_dir/js2c/asar_bundle.js",
|
||||
"$target_gen_dir/js2c/browser_init.js",
|
||||
"$target_gen_dir/js2c/isolated_bundle.js",
|
||||
"$target_gen_dir/js2c/node_init.js",
|
||||
"$target_gen_dir/js2c/renderer_init.js",
|
||||
"$target_gen_dir/js2c/sandbox_bundle.js",
|
||||
"$target_gen_dir/js2c/utility_init.js",
|
||||
"$target_gen_dir/js2c/worker_init.js",
|
||||
]
|
||||
|
||||
inputs = sources + [ "//third_party/electron_node/tools/js2c.py" ]
|
||||
inputs = sources
|
||||
outputs = [ "$root_gen_dir/electron_natives.cc" ]
|
||||
|
||||
script = "build/js2c.py"
|
||||
args = [ rebase_path("//third_party/electron_node") ] +
|
||||
rebase_path(outputs, root_build_dir) +
|
||||
rebase_path(sources, root_build_dir)
|
||||
out_dir =
|
||||
get_label_info(":anything($electron_js2c_toolchain)", "root_out_dir")
|
||||
args = [
|
||||
rebase_path("$out_dir/node_js2c"),
|
||||
rebase_path("$root_gen_dir"),
|
||||
] + rebase_path(outputs, root_gen_dir) +
|
||||
rebase_path(sources, root_gen_dir)
|
||||
}
|
||||
|
||||
action("generate_config_gypi") {
|
||||
@@ -486,6 +492,7 @@ source_set("electron_lib") {
|
||||
"//third_party/webrtc_overrides:webrtc_component",
|
||||
"//third_party/widevine/cdm:headers",
|
||||
"//third_party/zlib/google:zip",
|
||||
"//ui/base:ozone_buildflags",
|
||||
"//ui/base/idle",
|
||||
"//ui/compositor",
|
||||
"//ui/events:dom_keycode_converter",
|
||||
|
||||
11
DEPS
11
DEPS
@@ -2,9 +2,9 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'121.0.6104.0',
|
||||
'122.0.6261.70',
|
||||
'node_version':
|
||||
'v18.18.2',
|
||||
'v20.9.0',
|
||||
'nan_version':
|
||||
'e14bdcd1f72d62bca1d541b66da43130384ec213',
|
||||
'squirrel.mac_version':
|
||||
@@ -13,6 +13,8 @@ vars = {
|
||||
'74ab5baccc6f7202c8ac69a8d1e152c29dc1ea76',
|
||||
'mantle_version':
|
||||
'78d3966b3c331292ea29ec38661b25df0a245948',
|
||||
'engflow_reclient_configs_version':
|
||||
'955335c30a752e9ef7bff375baab5e0819b6c00d',
|
||||
|
||||
'pyyaml_version': '3.12',
|
||||
|
||||
@@ -23,6 +25,7 @@ vars = {
|
||||
'squirrel_git': 'https://github.com/Squirrel',
|
||||
'reactiveobjc_git': 'https://github.com/ReactiveCocoa',
|
||||
'mantle_git': 'https://github.com/Mantle',
|
||||
'engflow_git': 'https://github.com/EngFlow',
|
||||
|
||||
# The path of the sysroots.json file.
|
||||
'sysroots_json_path': 'electron/script/sysroots.json',
|
||||
@@ -102,6 +105,10 @@ deps = {
|
||||
'src/third_party/squirrel.mac/vendor/Mantle': {
|
||||
'url': Var("mantle_git") + '/Mantle.git@' + Var("mantle_version"),
|
||||
'condition': 'process_deps',
|
||||
},
|
||||
'src/third_party/engflow-reclient-configs': {
|
||||
'url': Var("engflow_git") + '/reclient-configs.git@' + Var("engflow_reclient_configs_version"),
|
||||
'condition': 'process_deps'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ environment:
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
|
||||
PYTHONIOENCODING: UTF-8
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-121.0.6100.0
|
||||
image: e-121.0.6116.0
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -37,7 +37,6 @@ environment:
|
||||
ELECTRON_ALSO_LOG_TO_STDERR: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, tap"
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 1
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN_BASE_URL: "https://dev-cdn.electronjs.org/windows-toolchains/_"
|
||||
GYP_MSVS_HASH_27370823e7: 28622d16b1
|
||||
@@ -101,31 +100,22 @@ for:
|
||||
if (Test-Path -Path "$pwd\src\electron") {
|
||||
Remove-Item -Recurse -Force $pwd\src\electron
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- npx yarn --ignore-engines
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..\..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
node -e "require('./src/utils/reclient.js').downloadAndPrepare({})"
|
||||
- ps: $env:RECLIENT_HELPER = node -p "require('./src/utils/reclient.js').helperPath({})"
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python3 $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
}
|
||||
& $env:RECLIENT_HELPER login
|
||||
- ps: >-
|
||||
$env:RBE_service = node -e "console.log(require('./src/utils/reclient.js').serviceAddress)"
|
||||
- ps: >-
|
||||
$env:RBE_experimental_credentials_helper = $env:RECLIENT_HELPER
|
||||
- ps: >-
|
||||
$env:RBE_experimental_credentials_helper_args = "print"
|
||||
- cd ..\..
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
@@ -147,36 +137,36 @@ for:
|
||||
- cd src
|
||||
- ps: $env:PATH="$pwd\third_party\ninja;$env:PATH"
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") use_remoteexec=true %GN_EXTRA_ARGS% "
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron/shell/common/api:mojo
|
||||
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
|
||||
- if DEFINED ELECTRON_RBE_JWT (autoninja -j 300 -C out/Default electron:electron_app) else (autoninja -C out/Default electron:electron_app)
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- ninja -C out/Default electron:electron_dist_zip
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") use_remoteexec=true %GN_EXTRA_ARGS%"
|
||||
- autoninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- autoninja -C out/Default electron:electron_dist_zip
|
||||
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/default_mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
- ps: >-
|
||||
Get-Content out/Default/default_mksnapshot_args | Where-Object { -not $_.Contains('--turbo-profiling-input') -And -not $_.Contains('builtins-pgo') -And -not $_.Contains('The gn arg use_goma=true') } | Set-Content out/Default/mksnapshot_args
|
||||
- ninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- autoninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- cd out\Default
|
||||
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
|
||||
- cd ..\..
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default electron:node_headers
|
||||
- python3 %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- autoninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- autoninja -C out/Default electron:electron_chromedriver_zip
|
||||
- autoninja -C out/Default electron:node_headers
|
||||
- ps: >-
|
||||
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
|
||||
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
- 7z a node_headers.zip out\Default\gen\node_headers
|
||||
- 7z a nan.zip third_party\nan
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
autoninja -C out/Default electron:electron_symbols
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
@@ -187,20 +177,28 @@ for:
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
- ps: |
|
||||
$manifest_file = "electron/script/zip_manifests/dist_zip.win.$env:TARGET_ARCH.manifest"
|
||||
python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip $manifest_file
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Zip contains files not listed in the manifest $manifest_file"
|
||||
}
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
|
||||
Write-warning "Skipping artifact validation for doc-only $env:APPVEYOR_PROJECT_NAME"
|
||||
} else {
|
||||
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
|
||||
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip','nan.zip'
|
||||
foreach($artifact_name in $artifacts_to_validate) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
} elseif (
|
||||
$artifact_name -eq 'node_headers.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} elseif (
|
||||
$artifact_name -eq 'nan.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} else {
|
||||
$artifact_file = "out\Default\$artifact_name"
|
||||
}
|
||||
@@ -235,6 +233,7 @@ for:
|
||||
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
|
||||
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
|
||||
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
|
||||
- if exist nan.zip (appveyor-retry appveyor PushArtifact nan.zip)
|
||||
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
|
||||
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
@@ -270,7 +269,7 @@ for:
|
||||
# Download build artifacts
|
||||
$apiUrl = 'https://ci.appveyor.com/api'
|
||||
$build_info = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/builds/$env:APPVEYOR_BUILD_ID"
|
||||
$artifacts_to_download = @('dist.zip','ffmpeg.zip','node_headers.zip','electron.lib')
|
||||
$artifacts_to_download = @('dist.zip','ffmpeg.zip','node_headers.zip','electron.lib', 'nan.zip')
|
||||
foreach ($job in $build_info.build.jobs) {
|
||||
if ($job.name -eq "Build Arm on X64 Windows") {
|
||||
$jobId = $job.jobId
|
||||
@@ -294,6 +293,7 @@ for:
|
||||
}
|
||||
- ps: 7z x -y -osrc\out\ffmpeg ffmpeg.zip
|
||||
- ps: 7z x -y -osrc node_headers.zip
|
||||
- ps: 7z x -y -osrc nan.zip
|
||||
|
||||
test_script:
|
||||
# Workaround for https://github.com/appveyor/ci/issues/2420
|
||||
|
||||
62
appveyor.yml
62
appveyor.yml
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-121.0.6100.0
|
||||
image: e-121.0.6116.0
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -37,7 +37,6 @@ environment:
|
||||
ELECTRON_ALSO_LOG_TO_STDERR: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, tap"
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 1
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN_BASE_URL: "https://dev-cdn.electronjs.org/windows-toolchains/_"
|
||||
GYP_MSVS_HASH_27370823e7: 28622d16b1
|
||||
@@ -99,31 +98,22 @@ for:
|
||||
if (Test-Path -Path "$pwd\src\electron") {
|
||||
Remove-Item -Recurse -Force $pwd\src\electron
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- npx yarn --ignore-engines
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..\..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
node -e "require('./src/utils/reclient.js').downloadAndPrepare({})"
|
||||
- ps: $env:RECLIENT_HELPER = node -p "require('./src/utils/reclient.js').helperPath({})"
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python3 $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
}
|
||||
& $env:RECLIENT_HELPER login
|
||||
- ps: >-
|
||||
$env:RBE_service = node -e "console.log(require('./src/utils/reclient.js').serviceAddress)"
|
||||
- ps: >-
|
||||
$env:RBE_experimental_credentials_helper = $env:RECLIENT_HELPER
|
||||
- ps: >-
|
||||
$env:RBE_experimental_credentials_helper_args = "print"
|
||||
- cd ..\..
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
@@ -145,27 +135,26 @@ for:
|
||||
- cd src
|
||||
- ps: $env:PATH="$pwd\third_party\ninja;$env:PATH"
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") use_remoteexec=true %GN_EXTRA_ARGS% "
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron/shell/common/api:mojo
|
||||
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
|
||||
- if DEFINED ELECTRON_RBE_JWT (autoninja -j 300 -C out/Default electron:electron_app) else (autoninja -C out/Default electron:electron_app)
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- ninja -C out/Default electron:electron_dist_zip
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") use_remoteexec=true %GN_EXTRA_ARGS%"
|
||||
- autoninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- autoninja -C out/Default electron:electron_dist_zip
|
||||
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/default_mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
- ps: >-
|
||||
Get-Content out/Default/default_mksnapshot_args | Where-Object { -not $_.Contains('--turbo-profiling-input') -And -not $_.Contains('builtins-pgo') -And -not $_.Contains('The gn arg use_goma=true') } | Set-Content out/Default/mksnapshot_args
|
||||
- ninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- autoninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- cd out\Default
|
||||
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
|
||||
- cd ..\..
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default electron:node_headers
|
||||
- python3 %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- autoninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- autoninja -C out/Default electron:electron_chromedriver_zip
|
||||
- autoninja -C out/Default electron:node_headers
|
||||
- ps: >-
|
||||
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
|
||||
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
@@ -174,7 +163,7 @@ for:
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
autoninja -C out/Default electron:electron_symbols
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
@@ -185,7 +174,12 @@ for:
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
- ps: |
|
||||
$manifest_file = "electron/script/zip_manifests/dist_zip.win.$env:TARGET_ARCH.manifest"
|
||||
python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip $manifest_file
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Zip contains files not listed in the manifest $manifest_file"
|
||||
}
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
|
||||
@@ -2,7 +2,7 @@ is_electron_build = true
|
||||
root_extra_deps = [ "//electron" ]
|
||||
|
||||
# Registry of NMVs --> https://github.com/nodejs/node/blob/main/doc/abi_version_registry.json
|
||||
node_module_version = 119
|
||||
node_module_version = 121
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_embedder_string = "-electron.0"
|
||||
@@ -24,6 +24,10 @@ enable_printing = true
|
||||
angle_enable_vulkan_validation_layers = false
|
||||
dawn_enable_vulkan_validation_layers = false
|
||||
|
||||
# Removes dxc dll's that are only used experimentally.
|
||||
# See https://bugs.chromium.org/p/chromium/issues/detail?id=1474897
|
||||
dawn_use_built_dxc = false
|
||||
|
||||
# These are disabled because they cause the zip manifest to differ between
|
||||
# testing and release builds.
|
||||
# See https://chromium-review.googlesource.com/c/chromium/src/+/2774898.
|
||||
@@ -61,7 +65,5 @@ enable_dangling_raw_ptr_checks = false
|
||||
# Ref: https://chromium-review.googlesource.com/c/v8/v8/+/4602858
|
||||
v8_enable_private_mapping_fork_optimization = true
|
||||
|
||||
# https://chromium-review.googlesource.com/c/chromium/src/+/4995136
|
||||
# TODO(jkleinsc): convert legacy IPC calls in extensions to use mojo
|
||||
# https://github.com/electron/electron/issues/40439
|
||||
enable_extensions_legacy_ipc = true
|
||||
# Expose public V8 symbols for native modules.
|
||||
v8_expose_public_symbols = true
|
||||
|
||||
@@ -32,6 +32,13 @@ extern const volatile char kFuseWire[];
|
||||
|
||||
TEMPLATE_CC = """
|
||||
#include "electron/fuses.h"
|
||||
#include "base/dcheck_is_on.h"
|
||||
|
||||
#if DCHECK_IS_ON()
|
||||
#include "base/command_line.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
namespace electron::fuses {
|
||||
|
||||
@@ -66,9 +73,20 @@ for fuse in fuses:
|
||||
getters_h += "FUSE_EXPORT bool Is{name}Enabled();\n".replace("{name}", name)
|
||||
getters_cc += """
|
||||
bool Is{name}Enabled() {
|
||||
#if DCHECK_IS_ON()
|
||||
// RunAsNode is checked so early that base::CommandLine isn't yet
|
||||
// initialized, so guard here to avoid a CHECK.
|
||||
if (base::CommandLine::InitializedForCurrentProcess()) {
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
if (command_line->HasSwitch("{switch_name}")) {
|
||||
std::string switch_value = command_line->GetSwitchValueASCII("{switch_name}");
|
||||
return switch_value == "1";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return kFuseWire[{index}] == '1';
|
||||
}
|
||||
""".replace("{name}", name).replace("{index}", str(index))
|
||||
""".replace("{name}", name).replace("{switch_name}", f"set-fuse-{fuse.lower()}").replace("{index}", str(index))
|
||||
|
||||
def c_hex(n):
|
||||
s = hex(n)[2:]
|
||||
|
||||
@@ -8,5 +8,6 @@
|
||||
"node_cli_inspect": "1",
|
||||
"embedded_asar_integrity_validation": "0",
|
||||
"only_load_app_from_asar": "0",
|
||||
"load_browser_process_specific_v8_snapshot": "0"
|
||||
"load_browser_process_specific_v8_snapshot": "0",
|
||||
"grant_file_protocol_extra_privileges": "1"
|
||||
}
|
||||
|
||||
30
build/js2c.py
Executable file → Normal file
30
build/js2c.py
Executable file → Normal file
@@ -4,32 +4,14 @@ import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
TEMPLATE = """
|
||||
#include "node_native_module.h"
|
||||
#include "node_internals.h"
|
||||
|
||||
namespace node::native_module {{
|
||||
|
||||
{definitions}
|
||||
|
||||
void NativeModuleLoader::LoadEmbedderJavaScriptSource() {{
|
||||
{initializers}
|
||||
}}
|
||||
|
||||
}} // namespace node::native_module
|
||||
"""
|
||||
|
||||
def main():
|
||||
node_path = os.path.abspath(sys.argv[1])
|
||||
natives = os.path.abspath(sys.argv[2])
|
||||
js_source_files = sys.argv[3:]
|
||||
js2c = sys.argv[1]
|
||||
root = sys.argv[2]
|
||||
natives = sys.argv[3]
|
||||
js_source_files = sys.argv[4:]
|
||||
|
||||
js2c = os.path.join(node_path, 'tools', 'js2c.py')
|
||||
subprocess.check_call(
|
||||
[sys.executable, js2c] +
|
||||
js_source_files +
|
||||
['--only-js', '--target', natives])
|
||||
|
||||
[js2c, natives] + js_source_files + ['--only-js', "--root", root])
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
sys.exit(main())
|
||||
@@ -1,10 +1,11 @@
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
def main(argv):
|
||||
cwd = argv[1]
|
||||
os.chdir(cwd)
|
||||
os.execv(sys.executable, [sys.executable] + argv[2:])
|
||||
os.chdir(argv[1])
|
||||
p = subprocess.Popen(argv[2:])
|
||||
return p.wait()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
sys.exit(main(sys.argv))
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'asar',
|
||||
alwaysHasNode: true,
|
||||
targetDeletesNodeGlobals: true
|
||||
});
|
||||
4
build/webpack/webpack.config.node.js
Normal file
4
build/webpack/webpack.config.node.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'node',
|
||||
alwaysHasNode: true
|
||||
});
|
||||
@@ -15,4 +15,15 @@ buildflag_header("buildflags") {
|
||||
"ENABLE_BUILTIN_SPELLCHECKER=$enable_builtin_spellchecker",
|
||||
"OVERRIDE_LOCATION_PROVIDER=$enable_fake_location_provider",
|
||||
]
|
||||
|
||||
if (electron_vendor_version != "") {
|
||||
result = string_split(electron_vendor_version, ":")
|
||||
flags += [
|
||||
"HAS_VENDOR_VERSION=true",
|
||||
"VENDOR_VERSION_NAME=\"${result[0]}\"",
|
||||
"VENDOR_VERSION_VALUE=\"${result[1]}\"",
|
||||
]
|
||||
} else {
|
||||
flags += [ "HAS_VENDOR_VERSION=false" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,4 +23,10 @@ declare_args() {
|
||||
# Packagers and vendor builders should set this in gn args to avoid running
|
||||
# the script that reads git tag.
|
||||
override_electron_version = ""
|
||||
|
||||
# Define an extra item that will show in process.versions, the value must
|
||||
# be in the format of "key:value".
|
||||
# Packagers and vendor builders can set this in gn args to attach extra info
|
||||
# about the build in the binary.
|
||||
electron_vendor_version = ""
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/devtools/devtools_file_system_indexer.cc",
|
||||
"//chrome/browser/devtools/devtools_file_system_indexer.h",
|
||||
"//chrome/browser/devtools/devtools_settings.h",
|
||||
"//chrome/browser/devtools/visual_logging.cc",
|
||||
"//chrome/browser/devtools/visual_logging.h",
|
||||
"//chrome/browser/extensions/global_shortcut_listener.cc",
|
||||
"//chrome/browser/extensions/global_shortcut_listener.h",
|
||||
"//chrome/browser/icon_loader.cc",
|
||||
@@ -57,8 +59,14 @@ static_library("chrome") {
|
||||
"//chrome/browser/net/proxy_service_factory.h",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_bounds_cache.cc",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_bounds_cache.h",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_occlusion_tracker.cc",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_occlusion_tracker.h",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_occlusion_tracker_observer.cc",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_occlusion_tracker_observer.h",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_window_manager.h",
|
||||
"//chrome/browser/picture_in_picture/scoped_picture_in_picture_occlusion_observation.cc",
|
||||
"//chrome/browser/picture_in_picture/scoped_picture_in_picture_occlusion_observation.h",
|
||||
"//chrome/browser/platform_util.cc",
|
||||
"//chrome/browser/platform_util.h",
|
||||
"//chrome/browser/predictors/preconnect_manager.cc",
|
||||
@@ -234,6 +242,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm",
|
||||
"//chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.h",
|
||||
"//chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.mm",
|
||||
"//chrome/browser/media/webrtc/thumbnail_capturer_mac.h",
|
||||
"//chrome/browser/media/webrtc/thumbnail_capturer_mac.mm",
|
||||
"//chrome/browser/media/webrtc/window_icon_util_mac.mm",
|
||||
"//chrome/browser/platform_util_mac.mm",
|
||||
"//chrome/browser/process_singleton_mac.mm",
|
||||
@@ -256,6 +266,8 @@ static_library("chrome") {
|
||||
sources += [
|
||||
"//chrome/browser/bad_message.cc",
|
||||
"//chrome/browser/bad_message.h",
|
||||
"//chrome/browser/printing/prefs_util.cc",
|
||||
"//chrome/browser/printing/prefs_util.h",
|
||||
"//chrome/browser/printing/print_job.cc",
|
||||
"//chrome/browser/printing/print_job.h",
|
||||
"//chrome/browser/printing/print_job_manager.cc",
|
||||
@@ -333,6 +345,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/pdf/pdf_extension_util.h",
|
||||
"//chrome/browser/pdf/pdf_frame_util.cc",
|
||||
"//chrome/browser/pdf/pdf_frame_util.h",
|
||||
"//chrome/browser/pdf/pdf_viewer_stream_manager.cc",
|
||||
"//chrome/browser/pdf/pdf_viewer_stream_manager.h",
|
||||
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.cc",
|
||||
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.h",
|
||||
]
|
||||
@@ -440,6 +454,8 @@ source_set("chrome_spellchecker") {
|
||||
"//chrome/browser/profiles/profile_selections.h",
|
||||
"//chrome/browser/spellchecker/spell_check_host_chrome_impl.cc",
|
||||
"//chrome/browser/spellchecker/spell_check_host_chrome_impl.h",
|
||||
"//chrome/browser/spellchecker/spell_check_initialization_host_impl.cc",
|
||||
"//chrome/browser/spellchecker/spell_check_initialization_host_impl.h",
|
||||
"//chrome/browser/spellchecker/spellcheck_custom_dictionary.cc",
|
||||
"//chrome/browser/spellchecker/spellcheck_custom_dictionary.h",
|
||||
"//chrome/browser/spellchecker/spellcheck_factory.cc",
|
||||
|
||||
@@ -15,7 +15,7 @@ Shortcuts are registered with the [`globalShortcut`](global-shortcut.md) module
|
||||
using the [`register`](global-shortcut.md#globalshortcutregisteraccelerator-callback)
|
||||
method, i.e.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, globalShortcut } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
|
||||
@@ -1468,6 +1468,24 @@ details.
|
||||
|
||||
**Note:** Enable `Secure Keyboard Entry` only when it is needed and disable it when it is no longer needed.
|
||||
|
||||
### `app.setProxy(config)`
|
||||
|
||||
* `config` [ProxyConfig](structures/proxy-config.md)
|
||||
|
||||
Returns `Promise<void>` - Resolves when the proxy setting process is complete.
|
||||
|
||||
Sets the proxy settings for networks requests made without an associated [Session](session.md).
|
||||
Currently this will affect requests made with [Net](net.md) in the [utility process](../glossary.md#utility-process)
|
||||
and internal requests made by the runtime (ex: geolocation queries).
|
||||
|
||||
This method can only be called after app is ready.
|
||||
|
||||
#### `app.resolveProxy(url)`
|
||||
|
||||
* `url` URL
|
||||
|
||||
Returns `Promise<string>` - Resolves with the proxy information for `url` that will be used when attempting to make requests using [Net](net.md) in the [utility process](../glossary.md#utility-process).
|
||||
|
||||
## Properties
|
||||
|
||||
### `app.accessibilitySupportEnabled` _macOS_ _Windows_
|
||||
@@ -1514,7 +1532,7 @@ A `boolean` property that returns `true` if the app is packaged, `false` otherw
|
||||
[tasks]:https://learn.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#tasks
|
||||
[app-user-model-id]: https://learn.microsoft.com/en-us/windows/win32/shell/appids
|
||||
[electron-forge]: https://www.electronforge.io/
|
||||
[electron-packager]: https://github.com/electron/electron-packager
|
||||
[electron-packager]: https://github.com/electron/packager
|
||||
[CFBundleURLTypes]: https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-102207-TPXREF115
|
||||
[LSCopyDefaultHandlerForURLScheme]: https://developer.apple.com/documentation/coreservices/1441725-lscopydefaulthandlerforurlscheme?language=objc
|
||||
[handoff]: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html
|
||||
|
||||
@@ -16,7 +16,7 @@ module is emitted.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// In the main process.
|
||||
const { app, BrowserView, BrowserWindow } = require('electron')
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Process: [Main](../glossary.md#main-process)
|
||||
This module cannot be used until the `ready` event of the `app`
|
||||
module is emitted.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// In the main process.
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
@@ -38,7 +38,7 @@ While loading the page, the `ready-to-show` event will be emitted when the rende
|
||||
process has rendered the page for the first time if the window has not been shown yet. Showing
|
||||
the window after this event will have no visual flash:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow({ show: false })
|
||||
win.once('ready-to-show', () => {
|
||||
@@ -59,7 +59,7 @@ For a complex app, the `ready-to-show` event could be emitted too late, making
|
||||
the app feel slow. In this case, it is recommended to show the window
|
||||
immediately, and use a `backgroundColor` close to your app's background:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
const win = new BrowserWindow({ backgroundColor: '#2e2c29' })
|
||||
@@ -85,7 +85,7 @@ For more information about these color types see valid options in [win.setBackgr
|
||||
|
||||
By using `parent` option, you can create child windows:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
const top = new BrowserWindow()
|
||||
@@ -101,7 +101,7 @@ The `child` window will always show on top of the `top` window.
|
||||
A modal window is a child window that disables parent window, to create a modal
|
||||
window, you have to set both `parent` and `modal` options:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
const top = new BrowserWindow()
|
||||
@@ -188,7 +188,7 @@ window should be closed, which will also be called when the window is
|
||||
reloaded. In Electron, returning any value other than `undefined` would cancel the
|
||||
close. For example:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
window.onbeforeunload = (e) => {
|
||||
console.log('I do not want to be closed')
|
||||
|
||||
@@ -351,7 +351,7 @@ Commands are lowercased, underscores are replaced with hyphens, and the
|
||||
`APPCOMMAND_` prefix is stripped off.
|
||||
e.g. `APPCOMMAND_BROWSER_BACKWARD` is emitted as `browser-backward`.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
win.on('app-command', (e, cmd) => {
|
||||
@@ -456,7 +456,7 @@ Returns `BrowserWindow | null` - The window with the given `id`.
|
||||
|
||||
Objects created with `new BrowserWindow` have the following properties:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
// In this example `win` is our instance
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
@@ -780,7 +780,7 @@ Closes the currently open [Quick Look][quick-look] panel.
|
||||
|
||||
Resizes and moves the window to the supplied bounds. Any properties that are not supplied will default to their current values.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
|
||||
@@ -1035,7 +1035,7 @@ Changes the attachment point for sheets on macOS. By default, sheets are
|
||||
attached just below the window frame, but you may want to display them beneath
|
||||
a HTML-rendered toolbar. For example:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
|
||||
@@ -1178,7 +1178,7 @@ To ensure that file URLs are properly formatted, it is recommended to use
|
||||
Node's [`url.format`](https://nodejs.org/api/url.html#url_url_format_urlobject)
|
||||
method:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
|
||||
@@ -1194,7 +1194,7 @@ win.loadURL(url)
|
||||
You can load a URL using a `POST` request with URL-encoded data by doing
|
||||
the following:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> Make HTTP/HTTPS requests.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)<br />
|
||||
Process: [Main](../glossary.md#main-process), [Utility](../glossary.md#utility-process)<br />
|
||||
_This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API._
|
||||
|
||||
`ClientRequest` implements the [Writable Stream](https://nodejs.org/api/stream.html#stream_writable_streams)
|
||||
@@ -65,7 +65,7 @@ strictly follow the Node.js model as described in the
|
||||
|
||||
For instance, we could have created the same request to 'github.com' as follows:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const request = net.request({
|
||||
method: 'GET',
|
||||
protocol: 'https:',
|
||||
@@ -104,7 +104,7 @@ The `callback` function is expected to be called back with user credentials:
|
||||
* `username` string
|
||||
* `password` string
|
||||
|
||||
```javascript @ts-type={request:Electron.ClientRequest}
|
||||
```js @ts-type={request:Electron.ClientRequest}
|
||||
request.on('login', (authInfo, callback) => {
|
||||
callback('username', 'password')
|
||||
})
|
||||
@@ -113,7 +113,7 @@ request.on('login', (authInfo, callback) => {
|
||||
Providing empty credentials will cancel the request and report an authentication
|
||||
error on the response object:
|
||||
|
||||
```javascript @ts-type={request:Electron.ClientRequest}
|
||||
```js @ts-type={request:Electron.ClientRequest}
|
||||
request.on('response', (response) => {
|
||||
console.log(`STATUS: ${response.statusCode}`)
|
||||
response.on('error', (error) => {
|
||||
|
||||
@@ -7,7 +7,7 @@ Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer
|
||||
On Linux, there is also a `selection` clipboard. To manipulate it
|
||||
you need to pass `selection` to each method:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { clipboard } = require('electron')
|
||||
|
||||
clipboard.writeText('Example string', 'selection')
|
||||
|
||||
@@ -6,7 +6,7 @@ You can use [app.commandLine.appendSwitch][append-switch] to append them in
|
||||
your app's main script before the [ready][ready] event of the [app][app] module
|
||||
is emitted:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app } = require('electron')
|
||||
app.commandLine.appendSwitch('remote-debugging-port', '8315')
|
||||
app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1')
|
||||
@@ -185,7 +185,7 @@ list of hosts. This flag has an effect only if used in tandem with
|
||||
|
||||
For example:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app } = require('electron')
|
||||
app.commandLine.appendSwitch('proxy-bypass-list', '<local>;*.google.com;*foo.com;1.2.3.4:5678')
|
||||
```
|
||||
|
||||
@@ -7,7 +7,7 @@ _This class is not exported from the `'electron'` module. It is only available a
|
||||
|
||||
The following example shows how to check if the `--disable-gpu` flag is set.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app } = require('electron')
|
||||
app.commandLine.hasSwitch('disable-gpu')
|
||||
```
|
||||
|
||||
@@ -10,7 +10,7 @@ This module does not include a web interface. To view recorded traces, use
|
||||
**Note:** You should not use this module until the `ready` event of the app
|
||||
module is emitted.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, contentTracing } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
|
||||
@@ -6,7 +6,7 @@ Process: [Renderer](../glossary.md#renderer-process)
|
||||
|
||||
An example of exposing an API to a renderer from an isolated preload script is given below:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// Preload (Isolated World)
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
@@ -18,7 +18,7 @@ contextBridge.exposeInMainWorld(
|
||||
)
|
||||
```
|
||||
|
||||
```javascript @ts-nocheck
|
||||
```js @ts-nocheck
|
||||
// Renderer (Main World)
|
||||
|
||||
window.electron.doThing()
|
||||
@@ -64,7 +64,7 @@ the API become immutable and updates on either side of the bridge do not result
|
||||
|
||||
An example of a complex API is shown below:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld(
|
||||
@@ -92,7 +92,7 @@ contextBridge.exposeInMainWorld(
|
||||
|
||||
An example of `exposeInIsolatedWorld` is shown below:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInIsolatedWorld(
|
||||
@@ -104,7 +104,7 @@ contextBridge.exposeInIsolatedWorld(
|
||||
)
|
||||
```
|
||||
|
||||
```javascript @ts-nocheck
|
||||
```js @ts-nocheck
|
||||
// Renderer (In isolated world id1004)
|
||||
|
||||
window.electron.doThing()
|
||||
@@ -145,7 +145,7 @@ The table of supported types described above also applies to Node APIs that you
|
||||
Please note that many Node APIs grant access to local system resources.
|
||||
Be very cautious about which globals and APIs you expose to untrusted remote content.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { contextBridge } = require('electron')
|
||||
const crypto = require('node:crypto')
|
||||
contextBridge.exposeInMainWorld('nodeCrypto', {
|
||||
|
||||
@@ -10,7 +10,7 @@ a `Session`.
|
||||
|
||||
For example:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { session } = require('electron')
|
||||
|
||||
// Query all cookies.
|
||||
|
||||
@@ -7,7 +7,7 @@ Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer
|
||||
The following is an example of setting up Electron to automatically submit
|
||||
crash reports to a remote server:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { crashReporter } = require('electron')
|
||||
|
||||
crashReporter.start({ submitURL: 'https://your-domain.com/url-to-submit' })
|
||||
|
||||
@@ -8,7 +8,7 @@ _This class is not exported from the `'electron'` module. It is only available a
|
||||
Chrome Developer Tools has a [special binding][rdp] available at JavaScript
|
||||
runtime that allows interacting with pages and instrumenting them.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Process: [Main](../glossary.md#main-process)
|
||||
The following example shows how to capture video from a desktop window whose
|
||||
title is `Electron`:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// In the main process.
|
||||
const { BrowserWindow, desktopCapturer } = require('electron')
|
||||
|
||||
@@ -24,7 +24,7 @@ desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources =
|
||||
})
|
||||
```
|
||||
|
||||
```javascript @ts-nocheck
|
||||
```js @ts-nocheck
|
||||
// In the preload script.
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
@@ -68,7 +68,7 @@ To capture both audio and video from the entire desktop the constraints passed
|
||||
to [`navigator.mediaDevices.getUserMedia`][] must include `chromeMediaSource: 'desktop'`,
|
||||
for both `audio` and `video`, but should not include a `chromeMediaSourceId` constraint.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const constraints = {
|
||||
audio: {
|
||||
mandatory: {
|
||||
|
||||
@@ -6,7 +6,7 @@ Process: [Main](../glossary.md#main-process)
|
||||
|
||||
An example of showing a dialog to select multiple files:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { dialog } = require('electron')
|
||||
console.log(dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] }))
|
||||
```
|
||||
@@ -52,7 +52,7 @@ The `browserWindow` argument allows the dialog to attach itself to a parent wind
|
||||
The `filters` specifies an array of file types that can be displayed or
|
||||
selected when you want to limit the user to a specific type. For example:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
{
|
||||
filters: [
|
||||
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
|
||||
@@ -119,7 +119,7 @@ The `browserWindow` argument allows the dialog to attach itself to a parent wind
|
||||
The `filters` specifies an array of file types that can be displayed or
|
||||
selected when you want to limit the user to a specific type. For example:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
{
|
||||
filters: [
|
||||
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
|
||||
|
||||
@@ -7,7 +7,7 @@ _This class is not exported from the `'electron'` module. It is only available a
|
||||
|
||||
The following example shows how to bounce your icon on the dock.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app } = require('electron')
|
||||
app.dock.bounce()
|
||||
```
|
||||
|
||||
@@ -9,7 +9,7 @@ _This class is not exported from the `'electron'` module. It is only available a
|
||||
It is used in `will-download` event of `Session` class, and allows users to
|
||||
control the download item.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// In the main process.
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
|
||||
@@ -59,7 +59,7 @@ geolocation webservice. To enable this feature, acquire a
|
||||
and place the following code in your main process file, before opening any
|
||||
browser windows that will make geolocation requests:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
process.env.GOOGLE_API_KEY = 'YOUR_KEY_HERE'
|
||||
```
|
||||
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
> Use the HTML5 `File` API to work natively with files on the filesystem.
|
||||
|
||||
> **Warning**
|
||||
> The `path` property that Electron adds to the `File` interface is deprecated
|
||||
> and **will** be removed in a future Electron release. We recommend you
|
||||
> use `webUtils.getPathForFile` instead.
|
||||
|
||||
The DOM's File interface provides abstraction around native files in order to
|
||||
let users work on native files directly with the HTML5 file API. Electron has
|
||||
added a `path` attribute to the `File` interface which exposes the file's real
|
||||
|
||||
@@ -12,7 +12,7 @@ shortcuts.
|
||||
not have the keyboard focus. This module cannot be used before the `ready`
|
||||
event of the app module is emitted.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, globalShortcut } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> Handle responses to HTTP/HTTPS requests.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)<br />
|
||||
Process: [Main](../glossary.md#main-process), [Utility](../glossary.md#utility-process)<br />
|
||||
_This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API._
|
||||
|
||||
`IncomingMessage` implements the [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams)
|
||||
@@ -89,7 +89,7 @@ tuples. So, the even-numbered offsets are key values, and the odd-numbered
|
||||
offsets are the associated values. Header names are not lowercased, and
|
||||
duplicates are not merged.
|
||||
|
||||
```javascript @ts-type={response:Electron.IncomingMessage}
|
||||
```js @ts-type={response:Electron.IncomingMessage}
|
||||
// Prints something like:
|
||||
//
|
||||
// [ 'user-agent',
|
||||
|
||||
@@ -120,7 +120,7 @@ The main process should listen for `channel` with
|
||||
|
||||
For example:
|
||||
|
||||
```javascript @ts-type={someArgument:unknown} @ts-type={doSomeWork:(arg:unknown)=>Promise<unknown>}
|
||||
```js @ts-type={someArgument:unknown} @ts-type={doSomeWork:(arg:unknown)=>Promise<unknown>}
|
||||
// Renderer process
|
||||
ipcRenderer.invoke('some-name', someArgument).then((result) => {
|
||||
// ...
|
||||
|
||||
@@ -151,7 +151,7 @@ can have a submenu.
|
||||
|
||||
An example of creating the application menu with the simple template API:
|
||||
|
||||
```javascript @ts-expect-error=[107]
|
||||
```js @ts-expect-error=[107]
|
||||
const { app, Menu } = require('electron')
|
||||
|
||||
const isMac = process.platform === 'darwin'
|
||||
@@ -353,7 +353,7 @@ By default, items will be inserted in the order they exist in the template unles
|
||||
|
||||
Template:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
[
|
||||
{ id: '1', label: 'one' },
|
||||
{ id: '2', label: 'two' },
|
||||
@@ -373,7 +373,7 @@ Menu:
|
||||
|
||||
Template:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
[
|
||||
{ id: '1', label: 'one' },
|
||||
{ type: 'separator' },
|
||||
@@ -397,7 +397,7 @@ Menu:
|
||||
|
||||
Template:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
[
|
||||
{ id: '1', label: 'one', after: ['3'] },
|
||||
{ id: '2', label: 'two', before: ['1'] },
|
||||
|
||||
@@ -10,7 +10,7 @@ In Electron, for the APIs that take images, you can pass either file paths or
|
||||
For example, when creating a tray or setting a window's icon, you can pass an
|
||||
image file path as a `string`:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow, Tray } = require('electron')
|
||||
|
||||
const appIcon = new Tray('/Users/somebody/images/icon.png')
|
||||
@@ -20,7 +20,7 @@ console.log(appIcon, win)
|
||||
|
||||
Or read the image from the clipboard, which returns a `NativeImage`:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { clipboard, Tray } = require('electron')
|
||||
const image = clipboard.readImage()
|
||||
const appIcon = new Tray(image)
|
||||
@@ -51,6 +51,13 @@ Check the _Size requirements_ section in [this article][icons].
|
||||
|
||||
[icons]: https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-icons
|
||||
|
||||
:::note
|
||||
|
||||
EXIF metadata is currently not supported and will not be taken into account during
|
||||
image encoding and decoding.
|
||||
|
||||
:::
|
||||
|
||||
## High Resolution Image
|
||||
|
||||
On platforms that have high-DPI support such as Apple Retina displays, you can
|
||||
@@ -71,7 +78,7 @@ images/
|
||||
└── icon@3x.png
|
||||
```
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { Tray } = require('electron')
|
||||
const appIcon = new Tray('/Users/somebody/images/icon.png')
|
||||
console.log(appIcon)
|
||||
@@ -138,7 +145,7 @@ Creates a new `NativeImage` instance from a file located at `path`. This method
|
||||
returns an empty image if the `path` does not exist, cannot be read, or is not
|
||||
a valid image.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const nativeImage = require('electron').nativeImage
|
||||
|
||||
const image = nativeImage.createFromPath('/Users/somebody/images/icon.png')
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, netLog } = require('electron')
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> Issue HTTP/HTTPS requests using Chromium's native networking library
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
Process: [Main](../glossary.md#main-process), [Utility](../glossary.md#utility-process)
|
||||
|
||||
The `net` module is a client-side API for issuing HTTP(S) requests. It is
|
||||
similar to the [HTTP](https://nodejs.org/api/http.html) and
|
||||
@@ -26,7 +26,7 @@ Node.js.
|
||||
|
||||
Example usage:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app } = require('electron')
|
||||
app.whenReady().then(() => {
|
||||
const { net } = require('electron')
|
||||
@@ -119,6 +119,9 @@ protocol.handle('https', (req) => {
|
||||
})
|
||||
```
|
||||
|
||||
Note: in the [utility process](../glossary.md#utility-process) custom protocols
|
||||
are not supported.
|
||||
|
||||
### `net.isOnline()`
|
||||
|
||||
Returns `boolean` - Whether there is currently internet connection.
|
||||
|
||||
@@ -6,7 +6,7 @@ Process: [Main](../glossary.md#main-process)
|
||||
|
||||
For example:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { powerSaveBlocker } = require('electron')
|
||||
|
||||
const id = powerSaveBlocker.start('prevent-display-sleep')
|
||||
|
||||
@@ -7,7 +7,7 @@ Process: [Main](../glossary.md#main-process)
|
||||
An example of implementing a protocol that has the same effect as the
|
||||
`file://` protocol:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, protocol, net } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
@@ -31,7 +31,7 @@ a different session and your custom protocol will not work if you just use
|
||||
To have your custom protocol work in combination with a custom session, you need
|
||||
to register it to that session explicitly.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, BrowserWindow, net, protocol, session } = require('electron')
|
||||
const path = require('node:path')
|
||||
const url = require('url')
|
||||
@@ -61,13 +61,14 @@ The `protocol` module has the following methods:
|
||||
module gets emitted and can be called only once.
|
||||
|
||||
Registers the `scheme` as standard, secure, bypasses content security policy for
|
||||
resources, allows registering ServiceWorker, supports fetch API, and streaming
|
||||
video/audio. Specify a privilege with the value of `true` to enable the capability.
|
||||
resources, allows registering ServiceWorker, supports fetch API, streaming
|
||||
video/audio, and V8 code cache. Specify a privilege with the value of `true` to
|
||||
enable the capability.
|
||||
|
||||
An example of registering a privileged scheme, that bypasses Content Security
|
||||
Policy:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { protocol } = require('electron')
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
{ scheme: 'foo', privileges: { bypassCSP: true } }
|
||||
@@ -122,7 +123,7 @@ Example:
|
||||
|
||||
```js
|
||||
const { app, net, protocol } = require('electron')
|
||||
const { join } = require('node:path')
|
||||
const path = require('node:path')
|
||||
const { pathToFileURL } = require('url')
|
||||
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
@@ -145,9 +146,19 @@ app.whenReady().then(() => {
|
||||
headers: { 'content-type': 'text/html' }
|
||||
})
|
||||
}
|
||||
// NB, this does not check for paths that escape the bundle, e.g.
|
||||
// NB, this checks for paths that escape the bundle, e.g.
|
||||
// app://bundle/../../secret_file.txt
|
||||
return net.fetch(pathToFileURL(join(__dirname, pathname)).toString())
|
||||
const pathToServe = path.resolve(__dirname, pathname)
|
||||
const relativePath = path.relative(__dirname, pathToServe)
|
||||
const isSafe = relativePath && !relativePath.startsWith('..') && !path.isAbsolute(relativePath)
|
||||
if (!isSafe) {
|
||||
return new Response('bad', {
|
||||
status: 400,
|
||||
headers: { 'content-type': 'text/html' }
|
||||
})
|
||||
}
|
||||
|
||||
return net.fetch(pathToFileURL(pathToServe).toString())
|
||||
} else if (host === 'api') {
|
||||
return net.fetch('https://api.my-server.com/' + pathname, {
|
||||
method: req.method,
|
||||
@@ -212,7 +223,7 @@ property.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
protocol.registerBufferProtocol('atom', (request, callback) => {
|
||||
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
|
||||
})
|
||||
@@ -267,7 +278,7 @@ has the `data` property.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { protocol } = require('electron')
|
||||
const { PassThrough } = require('stream')
|
||||
|
||||
@@ -292,7 +303,7 @@ protocol.registerStreamProtocol('atom', (request, callback) => {
|
||||
It is possible to pass any object that implements the readable stream API (emits
|
||||
`data`/`end`/`error` events). For example, here's how a file could be returned:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
protocol.registerStreamProtocol('atom', (request, callback) => {
|
||||
callback(fs.createReadStream('index.html'))
|
||||
})
|
||||
|
||||
@@ -6,7 +6,7 @@ Process: [Main](../glossary.md#main-process)
|
||||
|
||||
For example, when registering for push notifications via Apple push notification services (APNS):
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { pushNotifications, Notification } = require('electron')
|
||||
|
||||
pushNotifications.registerForAPNSNotifications().then((token) => {
|
||||
|
||||
@@ -14,20 +14,29 @@ property, so writing `let { screen } = require('electron')` will not work.
|
||||
|
||||
An example of creating a window that fills the whole screen:
|
||||
|
||||
```javascript fiddle='docs/fiddles/screen/fit-screen'
|
||||
const { app, BrowserWindow, screen } = require('electron')
|
||||
```fiddle docs/fiddles/screen/fit-screen
|
||||
// Retrieve information about screen size, displays, cursor position, etc.
|
||||
//
|
||||
// For more info, see:
|
||||
// https://www.electronjs.org/docs/latest/api/screen
|
||||
|
||||
const { app, BrowserWindow, screen } = require('electron/main')
|
||||
|
||||
let mainWindow = null
|
||||
|
||||
let win
|
||||
app.whenReady().then(() => {
|
||||
const { width, height } = screen.getPrimaryDisplay().workAreaSize
|
||||
win = new BrowserWindow({ width, height })
|
||||
win.loadURL('https://github.com')
|
||||
// Create a window that fills the screen's available work area.
|
||||
const primaryDisplay = screen.getPrimaryDisplay()
|
||||
const { width, height } = primaryDisplay.workAreaSize
|
||||
|
||||
mainWindow = new BrowserWindow({ width, height })
|
||||
mainWindow.loadURL('https://electronjs.org')
|
||||
})
|
||||
```
|
||||
|
||||
Another example of creating a window in the external display:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, BrowserWindow, screen } = require('electron')
|
||||
|
||||
let win
|
||||
|
||||
@@ -10,7 +10,7 @@ a `Session`.
|
||||
|
||||
For example:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { session } = require('electron')
|
||||
|
||||
// Get all service workers.
|
||||
|
||||
@@ -9,7 +9,7 @@ The `session` module can be used to create new `Session` objects.
|
||||
You can also access the `session` of existing pages by using the `session`
|
||||
property of [`WebContents`](web-contents.md), or from the `session` module.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
@@ -75,7 +75,7 @@ _This class is not exported from the `'electron'` module. It is only available a
|
||||
|
||||
You can create a `Session` object in the `session` module:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { session } = require('electron')
|
||||
const ses = session.fromPartition('persist:name')
|
||||
console.log(ses.getUserAgent())
|
||||
@@ -98,7 +98,7 @@ Emitted when Electron is about to download `item` in `webContents`.
|
||||
Calling `event.preventDefault()` will cancel the download and `item` will not be
|
||||
available from next tick of the process.
|
||||
|
||||
```javascript @ts-expect-error=[4]
|
||||
```js @ts-expect-error=[4]
|
||||
const { session } = require('electron')
|
||||
session.defaultSession.on('will-download', (event, item, webContents) => {
|
||||
event.preventDefault()
|
||||
@@ -214,7 +214,7 @@ cancel the request. Additionally, permissioning on `navigator.hid` can
|
||||
be further managed by using [`ses.setPermissionCheckHandler(handler)`](#sessetpermissioncheckhandlerhandler)
|
||||
and [`ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler).
|
||||
|
||||
```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
|
||||
```js @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let win = null
|
||||
@@ -266,7 +266,7 @@ Returns:
|
||||
|
||||
* `event` Event
|
||||
* `details` Object
|
||||
* `device` [HIDDevice[]](structures/hid-device.md)
|
||||
* `device` [HIDDevice](structures/hid-device.md)
|
||||
* `frame` [WebFrameMain](web-frame-main.md)
|
||||
|
||||
Emitted after `navigator.hid.requestDevice` has been called and
|
||||
@@ -281,7 +281,7 @@ Returns:
|
||||
|
||||
* `event` Event
|
||||
* `details` Object
|
||||
* `device` [HIDDevice[]](structures/hid-device.md)
|
||||
* `device` [HIDDevice](structures/hid-device.md)
|
||||
* `frame` [WebFrameMain](web-frame-main.md)
|
||||
|
||||
Emitted after `navigator.hid.requestDevice` has been called and
|
||||
@@ -296,7 +296,7 @@ Returns:
|
||||
|
||||
* `event` Event
|
||||
* `details` Object
|
||||
* `device` [HIDDevice[]](structures/hid-device.md)
|
||||
* `device` [HIDDevice](structures/hid-device.md)
|
||||
* `origin` string (optional) - The origin that the device has been revoked from.
|
||||
|
||||
Emitted after `HIDDevice.forget()` has been called. This event can be used
|
||||
@@ -320,7 +320,7 @@ cancel the request. Additionally, permissioning on `navigator.serial` can
|
||||
be managed by using [ses.setPermissionCheckHandler(handler)](#sessetpermissioncheckhandlerhandler)
|
||||
with the `serial` permission.
|
||||
|
||||
```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
|
||||
```js @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let win = null
|
||||
@@ -463,7 +463,7 @@ cancel the request. Additionally, permissioning on `navigator.usb` can
|
||||
be further managed by using [`ses.setPermissionCheckHandler(handler)`](#sessetpermissioncheckhandlerhandler)
|
||||
and [`ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler).
|
||||
|
||||
```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)} @ts-type={updateGrantedDevices:(devices:Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)=>void}
|
||||
```js @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)} @ts-type={updateGrantedDevices:(devices:Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)=>void}
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let win = null
|
||||
@@ -589,105 +589,15 @@ Writes any unwritten DOMStorage data to disk.
|
||||
|
||||
#### `ses.setProxy(config)`
|
||||
|
||||
* `config` Object
|
||||
* `mode` string (optional) - The proxy mode. Should be one of `direct`,
|
||||
`auto_detect`, `pac_script`, `fixed_servers` or `system`. If it's
|
||||
unspecified, it will be automatically determined based on other specified
|
||||
options.
|
||||
* `direct`
|
||||
In direct mode all connections are created directly, without any proxy involved.
|
||||
* `auto_detect`
|
||||
In auto_detect mode the proxy configuration is determined by a PAC script that can
|
||||
be downloaded at http://wpad/wpad.dat.
|
||||
* `pac_script`
|
||||
In pac_script mode the proxy configuration is determined by a PAC script that is
|
||||
retrieved from the URL specified in the `pacScript`. This is the default mode
|
||||
if `pacScript` is specified.
|
||||
* `fixed_servers`
|
||||
In fixed_servers mode the proxy configuration is specified in `proxyRules`.
|
||||
This is the default mode if `proxyRules` is specified.
|
||||
* `system`
|
||||
In system mode the proxy configuration is taken from the operating system.
|
||||
Note that the system mode is different from setting no proxy configuration.
|
||||
In the latter case, Electron falls back to the system settings
|
||||
only if no command-line options influence the proxy configuration.
|
||||
* `pacScript` string (optional) - The URL associated with the PAC file.
|
||||
* `proxyRules` string (optional) - Rules indicating which proxies to use.
|
||||
* `proxyBypassRules` string (optional) - Rules indicating which URLs should
|
||||
bypass the proxy settings.
|
||||
* `config` [ProxyConfig](structures/proxy-config.md)
|
||||
|
||||
Returns `Promise<void>` - Resolves when the proxy setting process is complete.
|
||||
|
||||
Sets the proxy settings.
|
||||
|
||||
When `mode` is unspecified, `pacScript` and `proxyRules` are provided together, the `proxyRules`
|
||||
option is ignored and `pacScript` configuration is applied.
|
||||
|
||||
You may need `ses.closeAllConnections` to close currently in flight connections to prevent
|
||||
pooled sockets using previous proxy from being reused by future requests.
|
||||
|
||||
The `proxyRules` has to follow the rules below:
|
||||
|
||||
```sh
|
||||
proxyRules = schemeProxies[";"<schemeProxies>]
|
||||
schemeProxies = [<urlScheme>"="]<proxyURIList>
|
||||
urlScheme = "http" | "https" | "ftp" | "socks"
|
||||
proxyURIList = <proxyURL>[","<proxyURIList>]
|
||||
proxyURL = [<proxyScheme>"://"]<proxyHost>[":"<proxyPort>]
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
* `http=foopy:80;ftp=foopy2` - Use HTTP proxy `foopy:80` for `http://` URLs, and
|
||||
HTTP proxy `foopy2:80` for `ftp://` URLs.
|
||||
* `foopy:80` - Use HTTP proxy `foopy:80` for all URLs.
|
||||
* `foopy:80,bar,direct://` - Use HTTP proxy `foopy:80` for all URLs, failing
|
||||
over to `bar` if `foopy:80` is unavailable, and after that using no proxy.
|
||||
* `socks4://foopy` - Use SOCKS v4 proxy `foopy:1080` for all URLs.
|
||||
* `http=foopy,socks5://bar.com` - Use HTTP proxy `foopy` for http URLs, and fail
|
||||
over to the SOCKS5 proxy `bar.com` if `foopy` is unavailable.
|
||||
* `http=foopy,direct://` - Use HTTP proxy `foopy` for http URLs, and use no
|
||||
proxy if `foopy` is unavailable.
|
||||
* `http=foopy;socks=foopy2` - Use HTTP proxy `foopy` for http URLs, and use
|
||||
`socks4://foopy2` for all other URLs.
|
||||
|
||||
The `proxyBypassRules` is a comma separated list of rules described below:
|
||||
|
||||
* `[ URL_SCHEME "://" ] HOSTNAME_PATTERN [ ":" <port> ]`
|
||||
|
||||
Match all hostnames that match the pattern HOSTNAME_PATTERN.
|
||||
|
||||
Examples:
|
||||
"foobar.com", "\*foobar.com", "\*.foobar.com", "\*foobar.com:99",
|
||||
"https://x.\*.y.com:99"
|
||||
|
||||
* `"." HOSTNAME_SUFFIX_PATTERN [ ":" PORT ]`
|
||||
|
||||
Match a particular domain suffix.
|
||||
|
||||
Examples:
|
||||
".google.com", ".com", "http://.google.com"
|
||||
|
||||
* `[ SCHEME "://" ] IP_LITERAL [ ":" PORT ]`
|
||||
|
||||
Match URLs which are IP address literals.
|
||||
|
||||
Examples:
|
||||
"127.0.1", "\[0:0::1]", "\[::1]", "http://\[::1]:99"
|
||||
|
||||
* `IP_LITERAL "/" PREFIX_LENGTH_IN_BITS`
|
||||
|
||||
Match any URL that is to an IP literal that falls between the
|
||||
given range. IP range is specified using CIDR notation.
|
||||
|
||||
Examples:
|
||||
"192.168.1.1/16", "fefe:13::abc/33".
|
||||
|
||||
* `<local>`
|
||||
|
||||
Match local addresses. The meaning of `<local>` is whether the
|
||||
host matches one of: "127.0.0.1", "::1", "localhost".
|
||||
|
||||
#### `ses.resolveHost(host, [options])`
|
||||
|
||||
* `host` string - Hostname to resolve.
|
||||
@@ -754,7 +664,7 @@ Sets download saving directory. By default, the download directory will be the
|
||||
|
||||
Emulates network with the given configuration for the `session`.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const win = new BrowserWindow()
|
||||
|
||||
// To emulate a GPRS connection with 50kbps throughput and 500 ms latency.
|
||||
@@ -868,7 +778,7 @@ calling `callback(-2)` rejects it.
|
||||
Calling `setCertificateVerifyProc(null)` will revert back to default certificate
|
||||
verify proc.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
|
||||
@@ -901,6 +811,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
|
||||
* `midiSysex` - Request the use of system exclusive messages in the [Web MIDI API](https://developer.mozilla.org/en-US/docs/Web/API/Web_MIDI_API).
|
||||
* `notifications` - Request notification creation and the ability to display them in the user's system tray using the [Notifications API](https://developer.mozilla.org/en-US/docs/Web/API/notification)
|
||||
* `pointerLock` - Request to directly interpret mouse movements as an input method via the [Pointer Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API). These requests always appear to originate from the main frame.
|
||||
* `keyboardLock` - Request capture of keypresses for any or all of the keys on the physical keyboard via the [Keyboard Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Keyboard/lock). These requests always appear to originate from the main frame.
|
||||
* `openExternal` - Request to open links in external applications.
|
||||
* `window-management` - Request access to enumerate screens using the [`getScreenDetails`](https://developer.chrome.com/en/articles/multi-screen-window-placement/) API.
|
||||
* `unknown` - An unrecognized permission request.
|
||||
@@ -920,7 +831,7 @@ To clear the handler, call `setPermissionRequestHandler(null)`. Please note tha
|
||||
you must also implement `setPermissionCheckHandler` to get complete permission handling.
|
||||
Most web APIs do a permission check and then make a permission request if the check is denied.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { session } = require('electron')
|
||||
session.fromPartition('some-partition').setPermissionRequestHandler((webContents, permission, callback) => {
|
||||
if (webContents.getURL() === 'some-host' && permission === 'notifications') {
|
||||
@@ -966,7 +877,7 @@ you must also implement `setPermissionRequestHandler` to get complete permission
|
||||
Most web APIs do a permission check and then make a permission request if the check is denied.
|
||||
To clear the handler, call `setPermissionCheckHandler(null)`.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { session } = require('electron')
|
||||
const url = require('url')
|
||||
session.fromPartition('some-partition').setPermissionCheckHandler((webContents, permission, requestingOrigin) => {
|
||||
@@ -1011,7 +922,7 @@ via the `navigator.mediaDevices.getDisplayMedia` API. Use the
|
||||
[desktopCapturer](desktop-capturer.md) API to choose which stream(s) to grant
|
||||
access to.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { session, desktopCapturer } = require('electron')
|
||||
|
||||
session.defaultSession.setDisplayMediaRequestHandler((request, callback) => {
|
||||
@@ -1025,7 +936,7 @@ session.defaultSession.setDisplayMediaRequestHandler((request, callback) => {
|
||||
Passing a [WebFrameMain](web-frame-main.md) object as a video or audio stream
|
||||
will capture the video or audio stream from that frame.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { session } = require('electron')
|
||||
|
||||
session.defaultSession.setDisplayMediaRequestHandler((request, callback) => {
|
||||
@@ -1054,7 +965,7 @@ Additionally, the default behavior of Electron is to store granted device permis
|
||||
If longer term storage is needed, a developer can store granted device
|
||||
permissions (eg when handling the `select-hid-device` event) and then read from that storage with `setDevicePermissionHandler`.
|
||||
|
||||
```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
|
||||
```js @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let win = null
|
||||
@@ -1136,7 +1047,7 @@ The return value for the handler is a string array of USB classes which should b
|
||||
Returning an empty string array from the handler will allow all USB classes; returning the passed in array will maintain the default list of protected USB classes (this is also the default behavior if a handler is not defined).
|
||||
To clear the handler, call `setUSBProtectedClassesHandler(null)`.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let win = null
|
||||
@@ -1191,7 +1102,7 @@ that requires additional validation will be automatically cancelled.
|
||||
macOS does not require a handler because macOS handles the pairing
|
||||
automatically. To clear the handler, call `setBluetoothPairingHandler(null)`.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, BrowserWindow, session } = require('electron')
|
||||
const path = require('node:path')
|
||||
|
||||
@@ -1237,7 +1148,7 @@ Clears the host resolver cache.
|
||||
Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate
|
||||
authentication.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { session } = require('electron')
|
||||
// consider any url ending with `example.com`, `foobar.com`, `baz`
|
||||
// for integrated authentication.
|
||||
@@ -1355,6 +1266,10 @@ registered.
|
||||
Sets the directory to store the generated JS [code cache](https://v8.dev/blog/code-caching-for-devs) for this session. The directory is not required to be created by the user before this call, the runtime will create if it does not exist otherwise will use the existing directory. If directory cannot be created, then code cache will not be used and all operations related to code cache will fail silently inside the runtime. By default, the directory will be `Code Cache` under the
|
||||
respective user data folder.
|
||||
|
||||
Note that by default code cache is only enabled for http(s) URLs, to enable code
|
||||
cache for custom protocols, `codeCache: true` and `standard: true` must be
|
||||
specified when registering the protocol.
|
||||
|
||||
#### `ses.clearCodeCaches(options)`
|
||||
|
||||
* `options` Object
|
||||
@@ -1542,7 +1457,7 @@ A [`WebRequest`](web-request.md) object for this session.
|
||||
|
||||
A [`Protocol`](protocol.md) object for this session.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, session } = require('electron')
|
||||
const path = require('node:path')
|
||||
|
||||
@@ -1561,7 +1476,7 @@ app.whenReady().then(() => {
|
||||
|
||||
A [`NetLog`](net-log.md) object for this session.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, session } = require('electron')
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
|
||||
@@ -8,7 +8,7 @@ The `shell` module provides functions related to desktop integration.
|
||||
|
||||
An example of opening a URL in the user's default browser:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { shell } = require('electron')
|
||||
|
||||
shell.openExternal('https://github.com')
|
||||
|
||||
@@ -9,3 +9,5 @@
|
||||
* `supportFetchAPI` boolean (optional) - Default false.
|
||||
* `corsEnabled` boolean (optional) - Default false.
|
||||
* `stream` boolean (optional) - Default false.
|
||||
* `codeCache` boolean (optional) - Enable V8 code cache for the scheme, only
|
||||
works when `standard` is also set to true. Default false.
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
# Display Object
|
||||
|
||||
* `id` number - Unique identifier associated with the display.
|
||||
* `accelerometerSupport` string - Can be `available`, `unavailable`, `unknown`.
|
||||
* `bounds` [Rectangle](rectangle.md) - the bounds of the display in DIP points.
|
||||
* `colorDepth` number - The number of bits per pixel.
|
||||
* `colorSpace` string - represent a color space (three-dimensional object which contains all realizable color combinations) for the purpose of color conversions.
|
||||
* `depthPerComponent` number - The number of bits per color component.
|
||||
* `detected` boolean - `true`` if the display is detected by the system.
|
||||
* `displayFrequency` number - The display refresh rate.
|
||||
* `id` number - Unique identifier associated with the display. A value of of -1 means the display is invalid or the correct `id` is not yet known, and a value of -10 means the display is a virtual display assigned to a unified desktop.
|
||||
* `internal` boolean - `true` for an internal display and `false` for an external display.
|
||||
* `label` string - User-friendly label, determined by the platform.
|
||||
* `maximumCursorSize` [Size](size.md) - Maximum cursor size in native pixels.
|
||||
* `nativeOrigin` [Point](point.md) - Returns the display's origin in pixel coordinates. Only available on windowing systems like X11 that position displays in pixel coordinates.
|
||||
* `rotation` number - Can be 0, 90, 180, 270, represents screen rotation in
|
||||
clock-wise degrees.
|
||||
* `scaleFactor` number - Output device's pixel scale factor.
|
||||
* `touchSupport` string - Can be `available`, `unavailable`, `unknown`.
|
||||
* `monochrome` boolean - Whether or not the display is a monochrome display.
|
||||
* `accelerometerSupport` string - Can be `available`, `unavailable`, `unknown`.
|
||||
* `colorSpace` string - represent a color space (three-dimensional object which contains all realizable color combinations) for the purpose of color conversions
|
||||
* `colorDepth` number - The number of bits per pixel.
|
||||
* `depthPerComponent` number - The number of bits per color component.
|
||||
* `displayFrequency` number - The display refresh rate.
|
||||
* `bounds` [Rectangle](rectangle.md) - the bounds of the display in DIP points.
|
||||
* `size` [Size](size.md)
|
||||
* `workArea` [Rectangle](rectangle.md) - the work area of the display in DIP points.
|
||||
* `workAreaSize` [Size](size.md)
|
||||
* `internal` boolean - `true` for an internal display and `false` for an external display
|
||||
* `workAreaSize` [Size](size.md) - The size of the work area.
|
||||
|
||||
The `Display` object represents a physical display connected to the system. A
|
||||
fake `Display` may exist on a headless system, or a `Display` may correspond to
|
||||
|
||||
@@ -14,7 +14,7 @@ The number represented by `status` means different things on different platforms
|
||||
Below is an example of some of the additional options that may be set which
|
||||
may be different on each platform.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
{
|
||||
name: 'Austin_4th_Floor_Printer___C02XK13BJHD4',
|
||||
displayName: 'Austin 4th Floor Printer @ C02XK13BJHD4',
|
||||
|
||||
86
docs/api/structures/proxy-config.md
Normal file
86
docs/api/structures/proxy-config.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# ProxyConfig Object
|
||||
|
||||
* `mode` string (optional) - The proxy mode. Should be one of `direct`,
|
||||
`auto_detect`, `pac_script`, `fixed_servers` or `system`.
|
||||
Defaults to `pac_script` proxy mode if `pacScript` option is specified
|
||||
otherwise defaults to `fixed_servers`.
|
||||
* `direct` - In direct mode all connections are created directly, without any proxy involved.
|
||||
* `auto_detect` - In auto_detect mode the proxy configuration is determined by a PAC script that can
|
||||
be downloaded at http://wpad/wpad.dat.
|
||||
* `pac_script` - In pac_script mode the proxy configuration is determined by a PAC script that is
|
||||
retrieved from the URL specified in the `pacScript`. This is the default mode if `pacScript` is specified.
|
||||
* `fixed_servers` - In fixed_servers mode the proxy configuration is specified in `proxyRules`.
|
||||
This is the default mode if `proxyRules` is specified.
|
||||
* `system` - In system mode the proxy configuration is taken from the operating system.
|
||||
Note that the system mode is different from setting no proxy configuration.
|
||||
In the latter case, Electron falls back to the system settings only if no
|
||||
command-line options influence the proxy configuration.
|
||||
* `pacScript` string (optional) - The URL associated with the PAC file.
|
||||
* `proxyRules` string (optional) - Rules indicating which proxies to use.
|
||||
* `proxyBypassRules` string (optional) - Rules indicating which URLs should
|
||||
bypass the proxy settings.
|
||||
|
||||
When `mode` is unspecified, `pacScript` and `proxyRules` are provided together, the `proxyRules`
|
||||
option is ignored and `pacScript` configuration is applied.
|
||||
|
||||
The `proxyRules` has to follow the rules below:
|
||||
|
||||
```sh
|
||||
proxyRules = schemeProxies[";"<schemeProxies>]
|
||||
schemeProxies = [<urlScheme>"="]<proxyURIList>
|
||||
urlScheme = "http" | "https" | "ftp" | "socks"
|
||||
proxyURIList = <proxyURL>[","<proxyURIList>]
|
||||
proxyURL = [<proxyScheme>"://"]<proxyHost>[":"<proxyPort>]
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
* `http=foopy:80;ftp=foopy2` - Use HTTP proxy `foopy:80` for `http://` URLs, and
|
||||
HTTP proxy `foopy2:80` for `ftp://` URLs.
|
||||
* `foopy:80` - Use HTTP proxy `foopy:80` for all URLs.
|
||||
* `foopy:80,bar,direct://` - Use HTTP proxy `foopy:80` for all URLs, failing
|
||||
over to `bar` if `foopy:80` is unavailable, and after that using no proxy.
|
||||
* `socks4://foopy` - Use SOCKS v4 proxy `foopy:1080` for all URLs.
|
||||
* `http=foopy,socks5://bar.com` - Use HTTP proxy `foopy` for http URLs, and fail
|
||||
over to the SOCKS5 proxy `bar.com` if `foopy` is unavailable.
|
||||
* `http=foopy,direct://` - Use HTTP proxy `foopy` for http URLs, and use no
|
||||
proxy if `foopy` is unavailable.
|
||||
* `http=foopy;socks=foopy2` - Use HTTP proxy `foopy` for http URLs, and use
|
||||
`socks4://foopy2` for all other URLs.
|
||||
|
||||
The `proxyBypassRules` is a comma separated list of rules described below:
|
||||
|
||||
* `[ URL_SCHEME "://" ] HOSTNAME_PATTERN [ ":" <port> ]`
|
||||
|
||||
Match all hostnames that match the pattern HOSTNAME_PATTERN.
|
||||
|
||||
Examples:
|
||||
"foobar.com", "\*foobar.com", "\*.foobar.com", "\*foobar.com:99",
|
||||
"https://x.\*.y.com:99"
|
||||
|
||||
* `"." HOSTNAME_SUFFIX_PATTERN [ ":" PORT ]`
|
||||
|
||||
Match a particular domain suffix.
|
||||
|
||||
Examples:
|
||||
".google.com", ".com", "http://.google.com"
|
||||
|
||||
* `[ SCHEME "://" ] IP_LITERAL [ ":" PORT ]`
|
||||
|
||||
Match URLs which are IP address literals.
|
||||
|
||||
Examples:
|
||||
"127.0.1", "\[0:0::1]", "\[::1]", "http://\[::1]:99"
|
||||
|
||||
* `IP_LITERAL "/" PREFIX_LENGTH_IN_BITS`
|
||||
|
||||
Match any URL that is to an IP literal that falls between the
|
||||
given range. IP range is specified using CIDR notation.
|
||||
|
||||
Examples:
|
||||
"192.168.1.1/16", "fefe:13::abc/33".
|
||||
|
||||
* `<local>`
|
||||
|
||||
Match local addresses. The meaning of `<local>` is whether the
|
||||
host matches one of: "127.0.0.1", "::1", "localhost".
|
||||
@@ -9,4 +9,4 @@
|
||||
* `array` Array\<unknown>
|
||||
* `dictionary` Record\<string, unknown>
|
||||
|
||||
This type is a helper alias, no object will never exist of this type.
|
||||
This type is a helper alias, no object will ever exist of this type.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { systemPreferences } = require('electron')
|
||||
console.log(systemPreferences.isAeroGlassEnabled())
|
||||
```
|
||||
@@ -189,7 +189,7 @@ enabled, and `false` otherwise.
|
||||
An example of using it to determine if you should create a transparent window or
|
||||
not (transparent windows won't work correctly when DWM composition is disabled):
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow, systemPreferences } = require('electron')
|
||||
const browserOptions = { width: 1000, height: 800 }
|
||||
|
||||
@@ -348,7 +348,7 @@ Returns `boolean` - whether or not this device has the ability to use Touch ID.
|
||||
|
||||
Returns `Promise<void>` - resolves if the user has successfully authenticated with Touch ID.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { systemPreferences } = require('electron')
|
||||
|
||||
systemPreferences.promptTouchID('To get consent for a Security-Gated Thing').then(success => {
|
||||
|
||||
@@ -79,7 +79,7 @@ immediately updates the escape item in the touch bar.
|
||||
Below is an example of a simple slot machine touch bar game with a button
|
||||
and some labels.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, BrowserWindow, TouchBar } = require('electron')
|
||||
|
||||
const { TouchBarLabel, TouchBarButton, TouchBarSpacer } = TouchBar
|
||||
|
||||
@@ -8,7 +8,7 @@ Process: [Main](../glossary.md#main-process)
|
||||
|
||||
`Tray` is an [EventEmitter][event-emitter].
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, Menu, Tray } = require('electron')
|
||||
|
||||
let tray = null
|
||||
@@ -39,7 +39,7 @@ app.whenReady().then(() => {
|
||||
* In order for changes made to individual `MenuItem`s to take effect,
|
||||
you have to call `setContextMenu` again. For example:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, Menu, Tray } = require('electron')
|
||||
|
||||
let appIcon = null
|
||||
|
||||
@@ -21,12 +21,11 @@ Process: [Main](../glossary.md#main-process)<br />
|
||||
of the child process. Default is `inherit`.
|
||||
String value can be one of `pipe`, `ignore`, `inherit`, for more details on these values you can refer to
|
||||
[stdio][] documentation from Node.js. Currently this option only supports configuring `stdout` and
|
||||
`stderr` to either `pipe`, `inherit` or `ignore`. Configuring `stdin` is not supported; `stdin` will
|
||||
always be ignored.
|
||||
`stderr` to either `pipe`, `inherit` or `ignore`. Configuring `stdin` to any property other than `ignore` is not supported and will result in an error.
|
||||
For example, the supported values will be processed as following:
|
||||
* `pipe`: equivalent to \['ignore', 'pipe', 'pipe'] (the default)
|
||||
* `pipe`: equivalent to \['ignore', 'pipe', 'pipe']
|
||||
* `ignore`: equivalent to \['ignore', 'ignore', 'ignore']
|
||||
* `inherit`: equivalent to \['ignore', 'inherit', 'inherit']
|
||||
* `inherit`: equivalent to \['ignore', 'inherit', 'inherit'] (the default)
|
||||
* `serviceName` string (optional) - Name of the process that will appear in `name` property of
|
||||
[`ProcessMetric`](structures/process-metric.md) returned by [`app.getAppMetrics`](app.md#appgetappmetrics)
|
||||
and [`child-process-gone` event of `app`](app.md#event-child-process-gone).
|
||||
|
||||
@@ -9,7 +9,7 @@ It is responsible for rendering and controlling a web page and is a property of
|
||||
the [`BrowserWindow`](browser-window.md) object. An example of accessing the
|
||||
`webContents` object:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
const win = new BrowserWindow({ width: 800, height: 1500 })
|
||||
@@ -53,7 +53,7 @@ If you want to also observe navigations in `<iframe>`s, use [`will-frame-navigat
|
||||
|
||||
These methods can be accessed from the `webContents` module:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { webContents } = require('electron')
|
||||
console.log(webContents)
|
||||
```
|
||||
@@ -439,7 +439,7 @@ Emitted when a `beforeunload` event handler is attempting to cancel a page unloa
|
||||
Calling `event.preventDefault()` will ignore the `beforeunload` event handler
|
||||
and allow the page to be unloaded.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow, dialog } = require('electron')
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.webContents.on('will-prevent-unload', (event) => {
|
||||
@@ -527,7 +527,7 @@ and the menu shortcuts.
|
||||
To only prevent the menu shortcuts, use
|
||||
[`setIgnoreMenuShortcuts`](#contentssetignoremenushortcutsignore):
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
@@ -837,7 +837,7 @@ Due to the nature of bluetooth, scanning for devices when
|
||||
`select-bluetooth-device` to fire multiple times until `callback` is called
|
||||
with either a device id or an empty string to cancel the request.
|
||||
|
||||
```javascript title='main.js'
|
||||
```js title='main.js'
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let win = null
|
||||
@@ -872,7 +872,7 @@ Returns:
|
||||
Emitted when a new frame is generated. Only the dirty area is passed in the
|
||||
buffer.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
const win = new BrowserWindow({ webPreferences: { offscreen: true } })
|
||||
@@ -1004,7 +1004,7 @@ Loads the `url` in the window. The `url` must contain the protocol prefix,
|
||||
e.g. the `http://` or `file://`. If the load should bypass http cache then
|
||||
use the `pragma` header to achieve it.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const win = new BrowserWindow()
|
||||
const options = { extraHeaders: 'pragma: no-cache\n' }
|
||||
win.webContents.loadURL('https://github.com', options)
|
||||
@@ -1054,7 +1054,7 @@ Initiates a download of the resource at `url` without navigating. The
|
||||
|
||||
Returns `string` - The URL of the current web page.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL('https://github.com').then(() => {
|
||||
@@ -1503,7 +1503,7 @@ can be obtained by subscribing to [`found-in-page`](web-contents.md#event-found-
|
||||
|
||||
Stops any `findInPage` request for the `webContents` with the provided `action`.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const win = new BrowserWindow()
|
||||
win.webContents.on('found-in-page', (event, result) => {
|
||||
if (result.finalUpdate) win.webContents.stopFindInPage('clearSelection')
|
||||
@@ -1614,6 +1614,7 @@ win.webContents.print(options, (success, errorType) => {
|
||||
* `footerTemplate` string (optional) - HTML template for the print footer. Should use the same format as the `headerTemplate`.
|
||||
* `preferCSSPageSize` boolean (optional) - Whether or not to prefer page size as defined by css. Defaults to false, in which case the content will be scaled to fit the paper size.
|
||||
* `generateTaggedPDF` boolean (optional) _Experimental_ - Whether or not to generate a tagged (accessible) PDF. Defaults to false. As this property is experimental, the generated PDF may not adhere fully to PDF/UA and WCAG standards.
|
||||
* `generateDocumentOutline` boolean (optional) _Experimental_ - Whether or not to generate a PDF document outline from content headers. Defaults to false.
|
||||
|
||||
Returns `Promise<Buffer>` - Resolves with the generated PDF data.
|
||||
|
||||
@@ -1623,25 +1624,27 @@ The `landscape` will be ignored if `@page` CSS at-rule is used in the web page.
|
||||
|
||||
An example of `webContents.printToPDF`:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
```js
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
const os = require('node:os')
|
||||
|
||||
const win = new BrowserWindow()
|
||||
win.loadURL('https://github.com')
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow()
|
||||
win.loadURL('https://github.com')
|
||||
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
// Use default printing options
|
||||
const pdfPath = path.join(os.homedir(), 'Desktop', 'temp.pdf')
|
||||
win.webContents.printToPDF({}).then(data => {
|
||||
fs.writeFile(pdfPath, data, (error) => {
|
||||
if (error) throw error
|
||||
console.log(`Wrote PDF successfully to ${pdfPath}`)
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
// Use default printing options
|
||||
const pdfPath = path.join(os.homedir(), 'Desktop', 'temp.pdf')
|
||||
win.webContents.printToPDF({}).then(data => {
|
||||
fs.writeFile(pdfPath, data, (error) => {
|
||||
if (error) throw error
|
||||
console.log(`Wrote PDF successfully to ${pdfPath}`)
|
||||
})
|
||||
}).catch(error => {
|
||||
console.log(`Failed to write PDF to ${pdfPath}: `, error)
|
||||
})
|
||||
}).catch(error => {
|
||||
console.log(`Failed to write PDF to ${pdfPath}: `, error)
|
||||
})
|
||||
})
|
||||
```
|
||||
@@ -1655,7 +1658,7 @@ See [Page.printToPdf](https://chromedevtools.github.io/devtools-protocol/tot/Pag
|
||||
Adds the specified path to DevTools workspace. Must be used after DevTools
|
||||
creation:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
win.webContents.on('devtools-opened', () => {
|
||||
@@ -1978,7 +1981,7 @@ the cursor when dragging.
|
||||
|
||||
Returns `Promise<void>` - resolves if the page is saved.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ The `webFrameMain` module can be used to lookup frames across existing
|
||||
[`WebContents`](web-contents.md) instances. Navigation events are the common
|
||||
use case.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow, webFrameMain } = require('electron')
|
||||
|
||||
const win = new BrowserWindow({ width: 800, height: 1500 })
|
||||
@@ -29,7 +29,7 @@ win.webContents.on(
|
||||
You can also access frames of existing pages by using the `mainFrame` property
|
||||
of [`WebContents`](web-contents.md).
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
async function main () {
|
||||
|
||||
@@ -10,7 +10,7 @@ certain properties and methods (e.g. `webFrame.firstChild`).
|
||||
|
||||
An example of zooming current page to 200%.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { webFrame } = require('electron')
|
||||
|
||||
webFrame.setZoomFactor(2)
|
||||
@@ -96,7 +96,7 @@ with an array of misspelt words when complete.
|
||||
|
||||
An example of using [node-spellchecker][spellchecker] as provider:
|
||||
|
||||
```javascript @ts-expect-error=[2,6]
|
||||
```js @ts-expect-error=[2,6]
|
||||
const { webFrame } = require('electron')
|
||||
const spellChecker = require('spellchecker')
|
||||
webFrame.setSpellCheckProvider('en-US', {
|
||||
@@ -205,14 +205,14 @@ Returns `Object`:
|
||||
Returns an object describing usage information of Blink's internal memory
|
||||
caches.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { webFrame } = require('electron')
|
||||
console.log(webFrame.getResourceUsage())
|
||||
```
|
||||
|
||||
This will generate:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
{
|
||||
images: {
|
||||
count: 22,
|
||||
|
||||
@@ -23,7 +23,7 @@ called with a `response` object when `listener` has done its work.
|
||||
|
||||
An example of adding `User-Agent` header for requests:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { session } = require('electron')
|
||||
|
||||
// Modify the user agent for all requests to the following urls.
|
||||
|
||||
26
docs/api/web-utils.md
Normal file
26
docs/api/web-utils.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# webUtils
|
||||
|
||||
> A utility layer to interact with Web API objects (Files, Blobs, etc.)
|
||||
|
||||
Process: [Renderer](../glossary.md#renderer-process)
|
||||
|
||||
## Methods
|
||||
|
||||
The `webUtils` module has the following methods:
|
||||
|
||||
### `webUtils.getPathForFile(file)`
|
||||
|
||||
* `file` File - A web [File](https://developer.mozilla.org/en-US/docs/Web/API/File) object.
|
||||
|
||||
Returns `string` - The file system path that this `File` object points to. In the case where the object passed in is not a `File` object an exception is thrown. In the case where the File object passed in was constructed in JS and is not backed by a file on disk an empty string is returned.
|
||||
|
||||
This method superceded the previous augmentation to the `File` object with the `path` property. An example is included below.
|
||||
|
||||
```js
|
||||
// Before
|
||||
const oldPath = document.querySelector('input').files[0].path
|
||||
|
||||
// After
|
||||
const { webUtils } = require('electron')
|
||||
const newPath = webUtils.getPathForFile(document.querySelector('input').files[0])
|
||||
```
|
||||
@@ -255,7 +255,7 @@ The `webview` tag has the following methods:
|
||||
|
||||
**Example**
|
||||
|
||||
```javascript @ts-expect-error=[3]
|
||||
```js @ts-expect-error=[3]
|
||||
const webview = document.querySelector('webview')
|
||||
webview.addEventListener('dom-ready', () => {
|
||||
webview.openDevTools()
|
||||
@@ -608,6 +608,7 @@ Prints `webview`'s web page. Same as `webContents.print([options])`.
|
||||
* `footerTemplate` string (optional) - HTML template for the print footer. Should use the same format as the `headerTemplate`.
|
||||
* `preferCSSPageSize` boolean (optional) - Whether or not to prefer page size as defined by css. Defaults to false, in which case the content will be scaled to fit the paper size.
|
||||
* `generateTaggedPDF` boolean (optional) _Experimental_ - Whether or not to generate a tagged (accessible) PDF. Defaults to false. As this property is experimental, the generated PDF may not adhere fully to PDF/UA and WCAG standards.
|
||||
* `generateDocumentOutline` boolean (optional) _Experimental_ - Whether or not to generate a PDF document outline from content headers. Defaults to false.
|
||||
|
||||
Returns `Promise<Uint8Array>` - Resolves with the generated PDF data.
|
||||
|
||||
@@ -802,7 +803,7 @@ Fired when the guest window logs a console message.
|
||||
The following example code forwards all log messages to the embedder's console
|
||||
without regard for log level or other properties.
|
||||
|
||||
```javascript @ts-expect-error=[3]
|
||||
```js @ts-expect-error=[3]
|
||||
const webview = document.querySelector('webview')
|
||||
webview.addEventListener('console-message', (e) => {
|
||||
console.log('Guest page logged a message:', e.message)
|
||||
@@ -823,7 +824,7 @@ Returns:
|
||||
Fired when a result is available for
|
||||
[`webview.findInPage`](#webviewfindinpagetext-options) request.
|
||||
|
||||
```javascript @ts-expect-error=[3,6]
|
||||
```js @ts-expect-error=[3,6]
|
||||
const webview = document.querySelector('webview')
|
||||
webview.addEventListener('found-in-page', (e) => {
|
||||
webview.stopFindInPage('keepSelection')
|
||||
@@ -948,7 +949,7 @@ Fired when the guest page attempts to close itself.
|
||||
The following example code navigates the `webview` to `about:blank` when the
|
||||
guest attempts to close itself.
|
||||
|
||||
```javascript @ts-expect-error=[3]
|
||||
```js @ts-expect-error=[3]
|
||||
const webview = document.querySelector('webview')
|
||||
webview.addEventListener('close', () => {
|
||||
webview.src = 'about:blank'
|
||||
@@ -968,7 +969,7 @@ Fired when the guest page has sent an asynchronous message to embedder page.
|
||||
With `sendToHost` method and `ipc-message` event you can communicate
|
||||
between guest page and embedder page:
|
||||
|
||||
```javascript @ts-expect-error=[4,7]
|
||||
```js @ts-expect-error=[4,7]
|
||||
// In embedder page.
|
||||
const webview = document.querySelector('webview')
|
||||
webview.addEventListener('ipc-message', (event) => {
|
||||
@@ -978,7 +979,7 @@ webview.addEventListener('ipc-message', (event) => {
|
||||
webview.send('ping')
|
||||
```
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// In guest page.
|
||||
const { ipcRenderer } = require('electron')
|
||||
ipcRenderer.on('ping', () => {
|
||||
|
||||
@@ -80,7 +80,7 @@ window will not close when the opener window closes. The default value is `false
|
||||
|
||||
### Native `Window` example
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// main.js
|
||||
const mainWindow = new BrowserWindow()
|
||||
|
||||
@@ -104,7 +104,7 @@ mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
})
|
||||
```
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// renderer process (mainWindow)
|
||||
const childWindow = window.open('', 'modal')
|
||||
childWindow.document.write('<h1>Hello</h1>')
|
||||
|
||||
@@ -12,14 +12,28 @@ This document uses the following convention to categorize breaking changes:
|
||||
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
|
||||
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
|
||||
|
||||
## Planned Breaking API Changes (30.0)
|
||||
|
||||
### Behavior Changed: cross-origin iframes now use Permission Policy to access features
|
||||
|
||||
Cross-origin iframes must now specify features available to a given `iframe` via the `allow`
|
||||
attribute in order to access them.
|
||||
|
||||
See [documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#allow) for
|
||||
more information.
|
||||
|
||||
### Removed: The `--disable-color-correct-rendering` switch
|
||||
|
||||
This switch was never formally documented but it's removal is being noted here regardless. Chromium itself now has better support for color spaces so this flag should not be needed.
|
||||
|
||||
## Planned Breaking API Changes (29.0)
|
||||
|
||||
### Behavior Changed: `ipcRenderer` can no longer be sent over the `contextBridge`
|
||||
|
||||
Attempting to send `ipcRenderer` as an object over the `contextBridge` will now result in
|
||||
Attempting to send the entire `ipcRenderer` module as an object over the `contextBridge` will now result in
|
||||
an empty object on the receiving side of the bridge. This change was made to remove / mitigate
|
||||
a security footgun, you should not directly expose ipcRenderer or it's methods over the bridge.
|
||||
Instead provide a safe wrapper like below:
|
||||
a security footgun. You should not directly expose ipcRenderer or its methods over the bridge.
|
||||
Instead, provide a safe wrapper like below:
|
||||
|
||||
```js
|
||||
contextBridge.exposeInMainWorld('app', {
|
||||
@@ -211,6 +225,18 @@ systemPreferences.on('high-contrast-color-scheme-changed', () => { /* ... */ })
|
||||
nativeTheme.on('updated', () => { /* ... */ })
|
||||
```
|
||||
|
||||
### Removed: Some `window.setVibrancy` options on macOS
|
||||
|
||||
The following vibrancy options have been removed:
|
||||
|
||||
* 'light'
|
||||
* 'medium-light'
|
||||
* 'dark'
|
||||
* 'ultra-dark'
|
||||
* 'appearance-based'
|
||||
|
||||
These were previously deprecated and have been removed by Apple in 10.15.
|
||||
|
||||
### Removed: `webContents.getPrinters`
|
||||
|
||||
The `webContents.getPrinters` method has been removed. Use
|
||||
@@ -590,7 +616,7 @@ The `new-window` event of `<webview>` has been removed. There is no direct repla
|
||||
webview.addEventListener('new-window', (event) => {})
|
||||
```
|
||||
|
||||
```javascript fiddle='docs/fiddles/ipc/webview-new-window'
|
||||
```js
|
||||
// Replace with
|
||||
|
||||
// main.js
|
||||
@@ -1255,7 +1281,7 @@ module](https://medium.com/@nornagon/electrons-remote-module-considered-harmful-
|
||||
|
||||
The APIs are now synchronous and the optional callback is no longer needed.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// Deprecated
|
||||
protocol.unregisterProtocol(scheme, () => { /* ... */ })
|
||||
// Replace with
|
||||
@@ -1284,7 +1310,7 @@ protocol.unregisterProtocol(scheme)
|
||||
|
||||
The APIs are now synchronous and the optional callback is no longer needed.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// Deprecated
|
||||
protocol.registerFileProtocol(scheme, handler, () => { /* ... */ })
|
||||
// Replace with
|
||||
@@ -1299,7 +1325,7 @@ until navigation happens.
|
||||
This API is deprecated and users should use `protocol.isProtocolRegistered`
|
||||
and `protocol.isProtocolIntercepted` instead.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// Deprecated
|
||||
protocol.isProtocolHandled(scheme).then(() => { /* ... */ })
|
||||
// Replace with
|
||||
|
||||
@@ -164,7 +164,7 @@ An example of the contents of this file can be found [here](https://github.com/e
|
||||
|
||||
Add your module to the module list found at `"lib/browser/api/module-list.ts"` like so:
|
||||
|
||||
```typescript title='lib/browser/api/module-list.ts' @ts-nocheck
|
||||
```ts title='lib/browser/api/module-list.ts' @ts-nocheck
|
||||
export const browserModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'apiName', loader: () => require('./api-name') },
|
||||
];
|
||||
|
||||
@@ -65,7 +65,7 @@ If you encounter this problem, the following articles may prove helpful:
|
||||
If you want a quick fix, you can make the variables global by changing your
|
||||
code from this:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, Tray } = require('electron')
|
||||
app.whenReady().then(() => {
|
||||
const tray = new Tray('/path/to/icon.png')
|
||||
@@ -75,7 +75,7 @@ app.whenReady().then(() => {
|
||||
|
||||
to this:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, Tray } = require('electron')
|
||||
let tray = null
|
||||
app.whenReady().then(() => {
|
||||
@@ -92,7 +92,7 @@ for some libraries since they want to insert the symbols with the same names.
|
||||
|
||||
To solve this, you can turn off node integration in Electron:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// In the main process.
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow({
|
||||
@@ -141,7 +141,7 @@ Sub-pixel anti-aliasing needs a non-transparent background of the layer containi
|
||||
|
||||
To achieve this goal, set the background in the constructor for [BrowserWindow][browser-window]:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow({
|
||||
backgroundColor: '#fff'
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<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
|
||||
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>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ including instances of `BrowserWindow`, `BrowserView`, and `WebView`. You
|
||||
can open them programmatically by calling the `openDevTools()` API on the
|
||||
`webContents` of the instance:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
const win = new BrowserWindow()
|
||||
|
||||
@@ -41,27 +41,27 @@ $ asar list /path/to/example.asar
|
||||
|
||||
Read a file in the ASAR archive:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const fs = require('node:fs')
|
||||
fs.readFileSync('/path/to/example.asar/file.txt')
|
||||
```
|
||||
|
||||
List all files under the root of the archive:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const fs = require('node:fs')
|
||||
fs.readdirSync('/path/to/example.asar')
|
||||
```
|
||||
|
||||
Use a module from the archive:
|
||||
|
||||
```javascript @ts-nocheck
|
||||
```js @ts-nocheck
|
||||
require('./path/to/example.asar/dir/module.js')
|
||||
```
|
||||
|
||||
You can also display a web page in an ASAR archive with `BrowserWindow`:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
|
||||
@@ -90,7 +90,7 @@ For some cases like verifying the ASAR archive's checksum, we need to read the
|
||||
content of an ASAR archive as a file. For this purpose you can use the built-in
|
||||
`original-fs` module which provides original `fs` APIs without `asar` support:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const originalFs = require('original-fs')
|
||||
originalFs.readFileSync('/path/to/example.asar')
|
||||
```
|
||||
@@ -98,7 +98,7 @@ originalFs.readFileSync('/path/to/example.asar')
|
||||
You can also set `process.noAsar` to `true` to disable the support for `asar` in
|
||||
the `fs` module:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const fs = require('node:fs')
|
||||
process.noAsar = true
|
||||
fs.readFileSync('/path/to/example.asar')
|
||||
|
||||
@@ -13,7 +13,7 @@ Currently ASAR integrity checking is only supported on macOS.
|
||||
|
||||
### Electron Forge / Electron Packager
|
||||
|
||||
If you are using `>= electron-packager@15.4.0` or `>= @electron-forge/core@6.0.0-beta.61` then all these requirements are met for you automatically and you can skip to [Toggling the Fuse](#toggling-the-fuse).
|
||||
If you are using `>= @electron/packager`, `>= electron-packager@15.4.0` or `>= @electron-forge/core@6.0.0-beta.61` then all these requirements are met for you automatically and you can skip to [Toggling the Fuse](#toggling-the-fuse).
|
||||
|
||||
### Other build systems
|
||||
|
||||
|
||||
@@ -196,32 +196,19 @@ support via Electron's support for the [Chrome DevTools Protocol][] (CDP).
|
||||
|
||||
### Install dependencies
|
||||
|
||||
You can install Playwright through your preferred Node.js package manager. The Playwright team
|
||||
recommends using the `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` environment variable to avoid
|
||||
unnecessary browser downloads when testing an Electron app.
|
||||
|
||||
```sh npm2yarn
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install --save-dev playwright
|
||||
```
|
||||
|
||||
Playwright also comes with its own test runner, Playwright Test, which is built for end-to-end
|
||||
testing. You can also install it as a dev dependency in your project:
|
||||
You can install Playwright through your preferred Node.js package manager. It comes with its
|
||||
own [test runner][playwright-intro], which is built for end-to-end testing:
|
||||
|
||||
```sh npm2yarn
|
||||
npm install --save-dev @playwright/test
|
||||
```
|
||||
|
||||
:::caution Dependencies
|
||||
This tutorial was written `playwright@1.16.3` and `@playwright/test@1.16.3`. Check out
|
||||
This tutorial was written with `@playwright/test@1.41.1`. Check out
|
||||
[Playwright's releases][playwright-releases] page to learn about
|
||||
changes that might affect the code below.
|
||||
:::
|
||||
|
||||
:::info Using third-party test runners
|
||||
If you're interested in using an alternative test runner (e.g. Jest or Mocha), check out
|
||||
Playwright's [Third-Party Test Runner][playwright-test-runners] guide.
|
||||
:::
|
||||
|
||||
### Write your tests
|
||||
|
||||
Playwright launches your app in development mode through the `_electron.launch` API.
|
||||
@@ -229,8 +216,7 @@ To point this API to your Electron app, you can pass the path to your main proce
|
||||
entry point (here, it is `main.js`).
|
||||
|
||||
```js {5} @ts-nocheck
|
||||
const { _electron: electron } = require('playwright')
|
||||
const { test } = require('@playwright/test')
|
||||
const { test, _electron: electron } = require('@playwright/test')
|
||||
|
||||
test('launch app', async () => {
|
||||
const electronApp = await electron.launch({ args: ['main.js'] })
|
||||
@@ -242,9 +228,8 @@ test('launch app', async () => {
|
||||
After that, you will access to an instance of Playwright's `ElectronApp` class. This
|
||||
is a powerful class that has access to main process modules for example:
|
||||
|
||||
```js {6-11} @ts-nocheck
|
||||
const { _electron: electron } = require('playwright')
|
||||
const { test } = require('@playwright/test')
|
||||
```js {5-10} @ts-nocheck
|
||||
const { test, _electron: electron } = require('@playwright/test')
|
||||
|
||||
test('get isPackaged', async () => {
|
||||
const electronApp = await electron.launch({ args: ['main.js'] })
|
||||
@@ -263,8 +248,7 @@ It can also create individual [Page][playwright-page] objects from Electron Brow
|
||||
For example, to grab the first BrowserWindow and save a screenshot:
|
||||
|
||||
```js {6-7} @ts-nocheck
|
||||
const { _electron: electron } = require('playwright')
|
||||
const { test } = require('@playwright/test')
|
||||
const { test, _electron: electron } = require('@playwright/test')
|
||||
|
||||
test('save screenshot', async () => {
|
||||
const electronApp = await electron.launch({ args: ['main.js'] })
|
||||
@@ -275,12 +259,11 @@ test('save screenshot', async () => {
|
||||
})
|
||||
```
|
||||
|
||||
Putting all this together using the PlayWright Test runner, let's create a `example.spec.js`
|
||||
Putting all this together using the Playwright test-runner, let's create a `example.spec.js`
|
||||
test file with a single test and assertion:
|
||||
|
||||
```js title='example.spec.js' @ts-nocheck
|
||||
const { _electron: electron } = require('playwright')
|
||||
const { test, expect } = require('@playwright/test')
|
||||
const { test, expect, _electron: electron } = require('@playwright/test')
|
||||
|
||||
test('example test', async () => {
|
||||
const electronApp = await electron.launch({ args: ['.'] })
|
||||
@@ -316,6 +299,7 @@ Running 1 test using 1 worker
|
||||
:::info
|
||||
Playwright Test will automatically run any files matching the `.*(test|spec)\.(js|ts|mjs)` regex.
|
||||
You can customize this match in the [Playwright Test configuration options][playwright-test-config].
|
||||
It also works with TypeScript out of the box.
|
||||
:::
|
||||
|
||||
:::tip Further reading
|
||||
@@ -473,10 +457,10 @@ test.after.always('cleanup', async t => {
|
||||
|
||||
[chrome-driver]: https://sites.google.com/chromium.org/driver/
|
||||
[Puppeteer]: https://github.com/puppeteer/puppeteer
|
||||
[playwright-intro]: https://playwright.dev/docs/intro
|
||||
[playwright-electron]: https://playwright.dev/docs/api/class-electron/
|
||||
[playwright-electronapplication]: https://playwright.dev/docs/api/class-electronapplication
|
||||
[playwright-page]: https://playwright.dev/docs/api/class-page
|
||||
[playwright-releases]: https://github.com/microsoft/playwright/releases
|
||||
[playwright-releases]: https://playwright.dev/docs/release-notes
|
||||
[playwright-test-config]: https://playwright.dev/docs/api/class-testconfig#test-config-test-match
|
||||
[playwright-test-runners]: https://playwright.dev/docs/test-runners/
|
||||
[Chrome DevTools Protocol]: https://chromedevtools.github.io/devtools-protocol/
|
||||
|
||||
@@ -30,7 +30,7 @@ Electron Forge is a tool for packaging and publishing Electron applications. It
|
||||
into a single extensible interface so that anyone can jump right into making Electron apps.
|
||||
|
||||
Forge comes with [a ready-to-use template](https://electronforge.io/templates) using Webpack as a bundler. It includes an example typescript configuration and provides two configuration files to enable easy customization. It uses the same core modules used by the
|
||||
greater Electron community (like [`electron-packager`](https://github.com/electron/electron-packager)) –
|
||||
greater Electron community (like [`@electron/packager`](https://github.com/electron/packager)) –
|
||||
changes made by Electron maintainers (like Slack) benefit Forge's users, too.
|
||||
|
||||
You can find more information and documentation on [electronforge.io](https://electronforge.io/).
|
||||
|
||||
@@ -51,7 +51,7 @@ ways to get your application signed and notarized.
|
||||
|
||||
If you're using Electron's favorite build tool, getting your application signed
|
||||
and notarized requires a few additions to your configuration. [Forge](https://electronforge.io) is a
|
||||
collection of the official Electron tools, using [`electron-packager`][],
|
||||
collection of the official Electron tools, using [`@electron/packager`][],
|
||||
[`@electron/osx-sign`][], and [`@electron/notarize`][] under the hood.
|
||||
|
||||
Detailed instructions on how to configure your application can be found in the
|
||||
@@ -61,14 +61,14 @@ the Electron Forge docs.
|
||||
### Using Electron Packager
|
||||
|
||||
If you're not using an integrated build pipeline like Forge, you
|
||||
are likely using [`electron-packager`][], which includes [`@electron/osx-sign`][] and
|
||||
are likely using [`@electron/packager`][], which includes [`@electron/osx-sign`][] and
|
||||
[`@electron/notarize`][].
|
||||
|
||||
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/main/interfaces/electronpackager.options.html).
|
||||
and notarizes your application](https://electron.github.io/packager/main/interfaces/electronpackager.options.html).
|
||||
|
||||
```js @ts-nocheck
|
||||
const packager = require('electron-packager')
|
||||
const packager = require('@electron/packager')
|
||||
|
||||
packager({
|
||||
dir: '/path/to/my/app',
|
||||
@@ -190,7 +190,7 @@ See the [Windows Store Guide][].
|
||||
|
||||
[apple developer program]: https://developer.apple.com/programs/
|
||||
[`@electron/osx-sign`]: https://github.com/electron/osx-sign
|
||||
[`electron-packager`]: https://github.com/electron/electron-packager
|
||||
[`@electron/packager`]: https://github.com/electron/packager
|
||||
[`@electron/notarize`]: https://github.com/electron/notarize
|
||||
[`electron-winstaller`]: https://github.com/electron/windows-installer
|
||||
[`electron-wix-msi`]: https://github.com/electron-userland/electron-wix-msi
|
||||
|
||||
@@ -16,7 +16,7 @@ Context isolation has been enabled by default since Electron 12, and it is a rec
|
||||
|
||||
Exposing APIs from your preload script to a loaded website in the renderer process is a common use-case. With context isolation disabled, your preload script would share a common global `window` object with the renderer. You could then attach arbitrary properties to a preload script:
|
||||
|
||||
```javascript title='preload.js' @ts-nocheck
|
||||
```js title='preload.js' @ts-nocheck
|
||||
// preload with contextIsolation disabled
|
||||
window.myAPI = {
|
||||
doAThing: () => {}
|
||||
@@ -25,7 +25,7 @@ window.myAPI = {
|
||||
|
||||
The `doAThing()` function could then be used directly in the renderer process:
|
||||
|
||||
```javascript title='renderer.js' @ts-nocheck
|
||||
```js title='renderer.js' @ts-nocheck
|
||||
// use the exposed API in the renderer
|
||||
window.myAPI.doAThing()
|
||||
```
|
||||
@@ -34,7 +34,7 @@ window.myAPI.doAThing()
|
||||
|
||||
There is a dedicated module in Electron to help you do this in a painless way. The [`contextBridge`](../api/context-bridge.md) module can be used to **safely** expose APIs from your preload script's isolated context to the context the website is running in. The API will also be accessible from the website on `window.myAPI` just like it was before.
|
||||
|
||||
```javascript title='preload.js'
|
||||
```js title='preload.js'
|
||||
// preload with contextIsolation enabled
|
||||
const { contextBridge } = require('electron')
|
||||
|
||||
@@ -43,7 +43,7 @@ contextBridge.exposeInMainWorld('myAPI', {
|
||||
})
|
||||
```
|
||||
|
||||
```javascript title='renderer.js' @ts-nocheck
|
||||
```js title='renderer.js' @ts-nocheck
|
||||
// use the exposed API in the renderer
|
||||
window.myAPI.doAThing()
|
||||
```
|
||||
@@ -54,7 +54,7 @@ Please read the `contextBridge` documentation linked above to fully understand i
|
||||
|
||||
Just enabling `contextIsolation` and using `contextBridge` does not automatically mean that everything you do is safe. For instance, this code is **unsafe**.
|
||||
|
||||
```javascript title='preload.js'
|
||||
```js title='preload.js'
|
||||
// ❌ Bad code
|
||||
contextBridge.exposeInMainWorld('myAPI', {
|
||||
send: ipcRenderer.send
|
||||
@@ -63,7 +63,7 @@ contextBridge.exposeInMainWorld('myAPI', {
|
||||
|
||||
It directly exposes a powerful API without any kind of argument filtering. This would allow any website to send arbitrary IPC messages, which you do not want to be possible. The correct way to expose IPC-based APIs would instead be to provide one method per IPC message.
|
||||
|
||||
```javascript title='preload.js'
|
||||
```js title='preload.js'
|
||||
// ✅ Good code
|
||||
contextBridge.exposeInMainWorld('myAPI', {
|
||||
loadPreferences: () => ipcRenderer.invoke('load-prefs')
|
||||
@@ -76,7 +76,7 @@ If you're building your Electron app with TypeScript, you'll want to add types t
|
||||
|
||||
For example, given this `preload.ts` script:
|
||||
|
||||
```typescript title='preload.ts'
|
||||
```ts title='preload.ts'
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
loadPreferences: () => ipcRenderer.invoke('load-prefs')
|
||||
})
|
||||
@@ -84,7 +84,7 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
||||
|
||||
You can create a `interface.d.ts` declaration file and globally augment the `Window` interface:
|
||||
|
||||
```typescript title='interface.d.ts' @ts-noisolate
|
||||
```ts title='interface.d.ts' @ts-noisolate
|
||||
export interface IElectronAPI {
|
||||
loadPreferences: () => Promise<void>,
|
||||
}
|
||||
@@ -98,7 +98,7 @@ declare global {
|
||||
|
||||
Doing so will ensure that the TypeScript compiler will know about the `electronAPI` property on your global `window` object when writing scripts in your renderer process:
|
||||
|
||||
```typescript title='renderer.ts'
|
||||
```ts title='renderer.ts'
|
||||
window.electronAPI.loadPreferences()
|
||||
```
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ of this theming, due to the use of the macOS 10.14 SDK.
|
||||
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.
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/dark-mode'
|
||||
```fiddle docs/fiddles/features/dark-mode
|
||||
|
||||
```
|
||||
|
||||
@@ -199,7 +199,7 @@ Run the example using Electron Fiddle and then click the "Toggle Dark Mode" butt
|
||||
|
||||
[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/main/interfaces/electronpackager.options.html#darwindarkmodesupport
|
||||
[electron-packager]: https://github.com/electron/packager
|
||||
[packager-darwindarkmode-api]: https://electron.github.io/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
|
||||
|
||||
@@ -26,14 +26,14 @@ This example demonstrates an Electron application that automatically selects
|
||||
the first available bluetooth device when the `Test Bluetooth` button is
|
||||
clicked.
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/web-bluetooth'
|
||||
```fiddle docs/fiddles/features/web-bluetooth
|
||||
|
||||
```
|
||||
|
||||
## WebHID API
|
||||
|
||||
The [WebHID API](https://web.dev/hid/) can be used to access HID devices such
|
||||
as keyboards and gamepads. Electron provides several APIs for working with
|
||||
as keyboards and gamepads. Electron provides several APIs for working with
|
||||
the WebHID API:
|
||||
|
||||
* The [`select-hid-device` event on the Session](../api/session.md#event-select-hid-device)
|
||||
@@ -61,7 +61,7 @@ By default Electron employs the same [blocklist](https://github.com/WICG/webhid/
|
||||
used by Chromium. If you wish to override this behavior, you can do so by
|
||||
setting the `disable-hid-blocklist` flag:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
app.commandLine.appendSwitch('disable-hid-blocklist')
|
||||
```
|
||||
|
||||
@@ -72,7 +72,7 @@ HID devices through [`ses.setDevicePermissionHandler(handler)`](../api/session.m
|
||||
and through [`select-hid-device` event on the Session](../api/session.md#event-select-hid-device)
|
||||
when the `Test WebHID` button is clicked.
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/web-hid'
|
||||
```fiddle docs/fiddles/features/web-hid
|
||||
|
||||
```
|
||||
|
||||
@@ -112,7 +112,7 @@ as well as demonstrating selecting the first available Arduino Uno serial device
|
||||
[`select-serial-port` event on the Session](../api/session.md#event-select-serial-port)
|
||||
when the `Test Web Serial` button is clicked.
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/web-serial'
|
||||
```fiddle docs/fiddles/features/web-serial
|
||||
|
||||
```
|
||||
|
||||
@@ -152,6 +152,6 @@ USB devices (if they are attached) through [`ses.setDevicePermissionHandler(hand
|
||||
and through [`select-usb-device` event on the Session](../api/session.md#event-select-usb-device)
|
||||
when the `Test WebUSB` button is clicked.
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/web-usb'
|
||||
```fiddle docs/fiddles/features/web-usb
|
||||
|
||||
```
|
||||
|
||||
@@ -33,7 +33,7 @@ Using the [React Developer Tools][react-devtools] as an example:
|
||||
1. Pass the location of the extension to the [`ses.loadExtension`][load-extension]
|
||||
API. For React Developer Tools `v4.9.0`, it looks something like:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, session } = require('electron')
|
||||
const path = require('node:path')
|
||||
const os = require('node:os')
|
||||
|
||||
@@ -9,10 +9,11 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
|
||||
| Electron | Alpha | Beta | Stable | EOL | Chrome | Node | Supported |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- | ---- | ---- |
|
||||
| 28.0.0 | 2023-Oct-11 | 2023-Nov-6 | 2023-Dec-5 | TBD | M120 | TBD | ✅ |
|
||||
| 29.0.0 | 2023-Dec-07 | 2024-Jan-24 | 2024-Feb-20 | 2024-Aug-20 | M122 | v18.19 | ✅ |
|
||||
| 28.0.0 | 2023-Oct-11 | 2023-Nov-06 | 2023-Dec-05 | 2024-Jun-11 | M120 | v18.18 | ✅ |
|
||||
| 27.0.0 | 2023-Aug-17 | 2023-Sep-13 | 2023-Oct-10 | 2024-Apr-16 | M118 | v18.17 | ✅ |
|
||||
| 26.0.0 | 2023-Jun-01 | 2023-Jun-27 | 2023-Aug-15 | 2024-Feb-27 | M116 | v18.16 | ✅ |
|
||||
| 25.0.0 | 2023-Apr-10 | 2023-May-02 | 2023-May-30 | 2024-Jan-02 | M114 | v18.15 | ✅ |
|
||||
| 26.0.0 | 2023-Jun-01 | 2023-Jun-27 | 2023-Aug-15 | 2024-Feb-20 | M116 | v18.16 | ✅ |
|
||||
| 25.0.0 | 2023-Apr-10 | 2023-May-02 | 2023-May-30 | 2023-Dec-05 | M114 | v18.15 | 🚫 |
|
||||
| 24.0.0 | 2023-Feb-09 | 2023-Mar-07 | 2023-Apr-04 | 2023-Oct-10 | M112 | v18.14 | 🚫 |
|
||||
| 23.0.0 | 2022-Dec-01 | 2023-Jan-10 | 2023-Feb-07 | 2023-Aug-15 | M110 | v18.12 | 🚫 |
|
||||
| 22.0.0 | 2022-Sep-29 | 2022-Oct-25 | 2022-Nov-29 | 2023-Oct-10 | M108 | v16.17 | 🚫 |
|
||||
@@ -37,6 +38,19 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | 2019-Jul-30 | M66 | v10.2 | 🚫 |
|
||||
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | 2019-Apr-23 | M61 | v8.9 | 🚫 |
|
||||
|
||||
:::info Official support dates may change
|
||||
|
||||
Electron's official support policy is the latest 3 stable releases. Our stable
|
||||
release and end-of-life dates are determined by Chromium, and may be subject to
|
||||
change. While we try to keep our planned release and end-of-life dates frequently
|
||||
updated here, future dates may change if affected by upstream scheduling changes,
|
||||
and may not always be accurately reflected.
|
||||
|
||||
See [Chromium's public release schedule](https://chromiumdash.appspot.com/schedule) for
|
||||
definitive information about Chromium's scheduled release dates.
|
||||
|
||||
:::
|
||||
|
||||
**Notes:**
|
||||
|
||||
* The `-alpha.1`, `-beta.1`, and `stable` dates are our solid release dates.
|
||||
@@ -48,20 +62,10 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
* Since Electron 5, Electron has been publicizing its release dates ([see blog post](https://www.electronjs.org/blog/electron-5-0-timeline)).
|
||||
* Since Electron 6, Electron major versions have been targeting every other Chromium major version. Each Electron stable should happen on the same day as Chrome stable ([see blog post](https://www.electronjs.org/blog/12-week-cadence)).
|
||||
* Since Electron 16, Electron has been releasing major versions on an 8-week cadence in accordance to Chrome's change to a 4-week release cadence ([see blog post](https://www.electronjs.org/blog/8-week-cadence)).
|
||||
* Electron temporarily extended support for Electron 22 until October 10, 2023, to support an extended end-of-life for Windows 7/8/8.1
|
||||
|
||||
## Version support policy
|
||||
|
||||
:::info
|
||||
|
||||
The Electron team will temporarily support Electron 22 until October 10, 2023.
|
||||
This extended support is intended to help Electron developers who still need
|
||||
support for Windows 7/8/8.1, which ended support in Electron 23. The October
|
||||
support date follows the extended support dates from both Chromium and Microsoft.
|
||||
On October 11, the Electron team will drop support back to the latest three
|
||||
stable major versions.
|
||||
|
||||
:::
|
||||
|
||||
The latest three _stable_ major versions are supported by the Electron team.
|
||||
For example, if the latest release is 6.1.x, then the 5.0.x as well
|
||||
as the 4.2.x series are supported. We only support the latest minor release
|
||||
|
||||
@@ -16,16 +16,7 @@ Once Fiddle is installed, you can press on the "Open in Fiddle" button that you
|
||||
will find below code samples like the following one:
|
||||
|
||||
```fiddle docs/fiddles/quick-start
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const replaceText = (selector, text) => {
|
||||
const element = document.getElementById(selector)
|
||||
if (element) element.innerText = text
|
||||
}
|
||||
|
||||
for (const type of ['chrome', 'node', 'electron']) {
|
||||
replaceText(`${type}-version`, process.versions[type])
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
If there is still something that you do not know how to do, please take a look at the [API][app]
|
||||
|
||||
@@ -15,7 +15,7 @@ Fuses are the solution to this problem, at a high level they are "magic bits" in
|
||||
**Default:** Enabled
|
||||
**@electron/fuses:** `FuseV1Options.RunAsNode`
|
||||
|
||||
The runAsNode fuse toggles whether the `ELECTRON_RUN_AS_NODE` environment variable is respected or not. Please note that if this fuse is disabled then `process.fork` in the main process will not function as expected as it depends on this environment variable to function.
|
||||
The runAsNode fuse toggles whether the `ELECTRON_RUN_AS_NODE` environment variable is respected or not. Please note that if this fuse is disabled then `process.fork` in the main process will not function as expected as it depends on this environment variable to function. Instead, we recommend that you use [Utility Processes](../api/utility-process.md), which work for many use cases where you need a standalone Node.js process (like a Sqlite server process or similar scenarios).
|
||||
|
||||
### `cookieEncryption`
|
||||
|
||||
@@ -61,6 +61,19 @@ The onlyLoadAppFromAsar fuse changes the search system that Electron uses to loc
|
||||
|
||||
The loadBrowserProcessSpecificV8Snapshot fuse changes which V8 snapshot file is used for the browser process. By default Electron's processes will all use the same V8 snapshot file. When this fuse is enabled the browser process uses the file called `browser_v8_context_snapshot.bin` for its V8 snapshot. The other processes will use the V8 snapshot file that they normally do.
|
||||
|
||||
### `grantFileProtocolExtraPrivileges`
|
||||
|
||||
**Default:** Enabled
|
||||
**@electron/fuses:** `FuseV1Options.GrantFileProtocolExtraPrivileges`
|
||||
|
||||
The grantFileProtocolExtraPrivileges fuse changes whether pages loaded from the `file://` protocol are given privileges beyond what they would receive in a traditional web browser. This behavior was core to Electron apps in original versions of Electron but is no longer required as apps should be [serving local files from custom protocols](./security.md#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) now instead. If you aren't serving pages from `file://` you should disable this fuse.
|
||||
|
||||
The extra privileges granted to the `file://` protocol by this fuse are incompletely documented below:
|
||||
|
||||
* `file://` protocol pages can use `fetch` to load other assets over `file://`
|
||||
* `file://` protocol pages can use service workers
|
||||
* `file://` protocol pages have universal access granted to child frames also running on `file://` protocols regardless of sandbox settings
|
||||
|
||||
## How do I flip the fuses?
|
||||
|
||||
### The easy way
|
||||
|
||||
@@ -34,7 +34,7 @@ To test In-App Purchase in development with Electron you'll have to change the `
|
||||
|
||||
Here is an example that shows how to use In-App Purchases in Electron. You'll have to replace the product ids by the identifiers of the products created with iTunes Connect (the identifier of `com.example.app.product1` is `product1`). Note that you have to listen to the `transactions-updated` event as soon as possible in your app.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// Main process
|
||||
const { inAppPurchase } = require('electron')
|
||||
const PRODUCT_IDS = ['id1', 'id2']
|
||||
@@ -107,7 +107,7 @@ if (!inAppPurchase.canMakePayments()) {
|
||||
inAppPurchase.getProducts(PRODUCT_IDS).then(products => {
|
||||
// Check the parameters.
|
||||
if (!Array.isArray(products) || products.length <= 0) {
|
||||
console.log('Unable to retrieve the product informations.')
|
||||
console.log('Unable to retrieve the product information.')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ You can use environment variables to override the base URL, the path at which to
|
||||
look for Electron binaries, and the binary filename. The URL used by `@electron/get`
|
||||
is composed as follows:
|
||||
|
||||
```javascript @ts-nocheck
|
||||
```js @ts-nocheck
|
||||
url = ELECTRON_MIRROR + ELECTRON_CUSTOM_DIR + '/' + ELECTRON_CUSTOM_FILENAME
|
||||
```
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ sections.
|
||||
|
||||
In the main process, set an IPC listener on the `set-title` channel with the `ipcMain.on` API:
|
||||
|
||||
```javascript {6-10,22} title='main.js (Main Process)'
|
||||
```js {6-10,22} title='main.js (Main Process)'
|
||||
const { app, BrowserWindow, ipcMain } = require('electron')
|
||||
const path = require('node:path')
|
||||
|
||||
@@ -96,7 +96,7 @@ you need to choose which APIs to expose from your preload script using the `cont
|
||||
In your preload script, add the following code, which will expose a global `window.electronAPI`
|
||||
variable to your renderer process.
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
```js title='preload.js (Preload Script)'
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
@@ -138,7 +138,7 @@ To make these elements interactive, we'll be adding a few lines of code in the i
|
||||
`renderer.js` file that leverages the `window.electronAPI` functionality exposed from the preload
|
||||
script:
|
||||
|
||||
```javascript title='renderer.js (Renderer Process)' @ts-expect-error=[4,5]
|
||||
```js title='renderer.js (Renderer Process)' @ts-expect-error=[4,5]
|
||||
const setButton = document.getElementById('btn')
|
||||
const titleInput = document.getElementById('title')
|
||||
setButton.addEventListener('click', () => {
|
||||
@@ -181,7 +181,7 @@ provided to the renderer process. Please refer to
|
||||
[#24427](https://github.com/electron/electron/issues/24427) for details.
|
||||
:::
|
||||
|
||||
```javascript {6-13,25} title='main.js (Main Process)'
|
||||
```js {6-13,25} title='main.js (Main Process)'
|
||||
const { app, BrowserWindow, dialog, ipcMain } = require('electron')
|
||||
const path = require('node:path')
|
||||
|
||||
@@ -225,7 +225,7 @@ In the preload script, we expose a one-line `openFile` function that calls and r
|
||||
`ipcRenderer.invoke('dialog:openFile')`. We'll be using this API in the next step to call the
|
||||
native dialog from our renderer's user interface.
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
```js title='preload.js (Preload Script)'
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
@@ -263,7 +263,7 @@ The UI consists of a single `#btn` button element that will be used to trigger o
|
||||
a `#filePath` element that will be used to display the path of the selected file. Making these
|
||||
pieces work will take a few lines of code in the renderer process script:
|
||||
|
||||
```javascript title='renderer.js (Renderer Process)' @ts-expect-error=[5]
|
||||
```js title='renderer.js (Renderer Process)' @ts-expect-error=[5]
|
||||
const btn = document.getElementById('btn')
|
||||
const filePathElement = document.getElementById('filePath')
|
||||
|
||||
@@ -280,8 +280,8 @@ selected file path in the `#filePath` element.
|
||||
### Note: legacy approaches
|
||||
|
||||
The `ipcRenderer.invoke` API was added in Electron 7 as a developer-friendly way to tackle two-way
|
||||
IPC from the renderer process. However, there exist a couple alternative approaches to this IPC
|
||||
pattern.
|
||||
IPC from the renderer process. However, a couple of alternative approaches to this IPC pattern
|
||||
exist.
|
||||
|
||||
:::warning Avoid legacy approaches if possible
|
||||
We recommend using `ipcRenderer.invoke` whenever possible. The following two-way renderer-to-main
|
||||
@@ -299,7 +299,7 @@ The `ipcRenderer.send` API that we used for single-way communication can also be
|
||||
perform two-way communication. This was the recommended way for asynchronous two-way communication
|
||||
via IPC prior to Electron 7.
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
```js title='preload.js (Preload Script)'
|
||||
// You can also put expose this code to the renderer
|
||||
// process with the `contextBridge` API
|
||||
const { ipcRenderer } = require('electron')
|
||||
@@ -310,7 +310,7 @@ ipcRenderer.on('asynchronous-reply', (_event, arg) => {
|
||||
ipcRenderer.send('asynchronous-message', 'ping')
|
||||
```
|
||||
|
||||
```javascript title='main.js (Main Process)'
|
||||
```js title='main.js (Main Process)'
|
||||
ipcMain.on('asynchronous-message', (event, arg) => {
|
||||
console.log(arg) // prints "ping" in the Node console
|
||||
// works like `send`, but returning a message back
|
||||
@@ -332,7 +332,7 @@ channels, you would need to add additional app code to track each call and respo
|
||||
The `ipcRenderer.sendSync` API sends a message to the main process and waits _synchronously_ for a
|
||||
response.
|
||||
|
||||
```javascript title='main.js (Main Process)'
|
||||
```js title='main.js (Main Process)'
|
||||
const { ipcMain } = require('electron')
|
||||
ipcMain.on('synchronous-message', (event, arg) => {
|
||||
console.log(arg) // prints "ping" in the Node console
|
||||
@@ -340,7 +340,7 @@ ipcMain.on('synchronous-message', (event, arg) => {
|
||||
})
|
||||
```
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
```js title='preload.js (Preload Script)'
|
||||
// You can also put expose this code to the renderer
|
||||
// process with the `contextBridge` API
|
||||
const { ipcRenderer } = require('electron')
|
||||
@@ -376,7 +376,7 @@ For this demo, we'll need to first build a custom menu in the main process using
|
||||
module that uses the `webContents.send` API to send an IPC message from the main process to the
|
||||
target renderer.
|
||||
|
||||
```javascript {11-26} title='main.js (Main Process)'
|
||||
```js {11-26} title='main.js (Main Process)'
|
||||
const { app, BrowserWindow, Menu, ipcMain } = require('electron')
|
||||
const path = require('node:path')
|
||||
|
||||
@@ -412,7 +412,7 @@ function createWindow () {
|
||||
For the purposes of the tutorial, it's important to note that the `click` handler
|
||||
sends a message (either `1` or `-1`) to the renderer process through the `update-counter` channel.
|
||||
|
||||
```javascript @ts-type={mainWindow:Electron.BrowserWindow}
|
||||
```js @ts-type={mainWindow:Electron.BrowserWindow}
|
||||
click: () => mainWindow.webContents.send('update-counter', -1)
|
||||
```
|
||||
|
||||
@@ -425,7 +425,7 @@ Make sure you're loading the `index.html` and `preload.js` entry points for the
|
||||
Like in the previous renderer-to-main example, we use the `contextBridge` and `ipcRenderer`
|
||||
modules in the preload script to expose IPC functionality to the renderer process:
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
```js title='preload.js (Preload Script)'
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
@@ -447,7 +447,7 @@ Use a custom handler that invoke the `callback` only with the desired arguments.
|
||||
In the case of this minimal example, you can call `ipcRenderer.on` directly in the preload script
|
||||
rather than exposing it over the context bridge.
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
```js title='preload.js (Preload Script)'
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
@@ -488,7 +488,7 @@ To tie it all together, we'll create an interface in the loaded HTML file that c
|
||||
Finally, to make the values update in the HTML document, we'll add a few lines of DOM manipulation
|
||||
so that the value of the `#counter` element is updated whenever we fire an `update-counter` event.
|
||||
|
||||
```javascript title='renderer.js (Renderer Process)' @ts-window-type={electronAPI:{onUpdateCounter:(callback:(value:number)=>void)=>void}}
|
||||
```js title='renderer.js (Renderer Process)' @ts-window-type={electronAPI:{onUpdateCounter:(callback:(value:number)=>void)=>void}}
|
||||
const counter = document.getElementById('counter')
|
||||
|
||||
window.electronAPI.onUpdateCounter((value) => {
|
||||
@@ -511,7 +511,7 @@ We can demonstrate this with slight modifications to the code from the previous
|
||||
renderer process, expose another API to send a reply back to the main process through the
|
||||
`counter-value` channel.
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
```js title='preload.js (Preload Script)'
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
@@ -520,7 +520,7 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
||||
})
|
||||
```
|
||||
|
||||
```javascript title='renderer.js (Renderer Process)' @ts-window-type={electronAPI:{onUpdateCounter:(callback:(value:number)=>void)=>void,counterValue:(value:number)=>void}}
|
||||
```js title='renderer.js (Renderer Process)' @ts-window-type={electronAPI:{onUpdateCounter:(callback:(value:number)=>void)=>void,counterValue:(value:number)=>void}}
|
||||
const counter = document.getElementById('counter')
|
||||
|
||||
window.electronAPI.onUpdateCounter((value) => {
|
||||
@@ -533,7 +533,7 @@ window.electronAPI.onUpdateCounter((value) => {
|
||||
|
||||
In the main process, listen for `counter-value` events and handle them appropriately.
|
||||
|
||||
```javascript title='main.js (Main Process)'
|
||||
```js title='main.js (Main Process)'
|
||||
// ...
|
||||
ipcMain.on('counter-value', (_event, value) => {
|
||||
console.log(value) // will print value to Node console
|
||||
|
||||
@@ -14,11 +14,19 @@ To configure a local keyboard shortcut, you need to specify an [`accelerator`][]
|
||||
property when creating a [MenuItem][] within the [Menu][] module.
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the
|
||||
following lines:
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` to be:
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/local'
|
||||
const { Menu, MenuItem } = require('electron')
|
||||
```fiddle docs/fiddles/features/keyboard-shortcuts/local
|
||||
const { app, BrowserWindow, Menu, MenuItem } = require('electron/main')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
const menu = new Menu()
|
||||
menu.append(new MenuItem({
|
||||
@@ -31,6 +39,20 @@ menu.append(new MenuItem({
|
||||
}))
|
||||
|
||||
Menu.setApplicationMenu(menu)
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
> NOTE: In the code above, you can see that the accelerator differs based on the
|
||||
@@ -53,17 +75,37 @@ module to detect keyboard events even when the application does not have
|
||||
keyboard focus.
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the
|
||||
following lines:
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` to be:
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/global' @ts-type={createWindow:()=>void}
|
||||
const { app, globalShortcut } = require('electron')
|
||||
```fiddle docs/fiddles/features/keyboard-shortcuts/global
|
||||
const { app, BrowserWindow, globalShortcut } = require('electron/main')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
globalShortcut.register('Alt+CommandOrControl+I', () => {
|
||||
console.log('Electron loves global shortcuts!')
|
||||
})
|
||||
}).then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
> NOTE: In the code above, the `CommandOrControl` combination uses `Command`
|
||||
@@ -81,8 +123,8 @@ If you want to handle keyboard shortcuts within a [BrowserWindow][], you can
|
||||
listen for the `keyup` and `keydown` [DOM events][dom-events] inside the
|
||||
renderer process using the [addEventListener() API][addEventListener-api].
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/web-apis|focus=renderer.js'
|
||||
const handleKeyPress = (event) => {
|
||||
```fiddle docs/fiddles/features/keyboard-shortcuts/web-apis|focus=renderer.js
|
||||
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}`)
|
||||
@@ -105,8 +147,8 @@ Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the
|
||||
following lines:
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/interception-from-main'
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
```fiddle docs/fiddles/features/keyboard-shortcuts/interception-from-main
|
||||
const { app, BrowserWindow } = require('electron/main')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
|
||||
@@ -25,14 +25,14 @@ we will use will be "`electron-fiddle://`".
|
||||
First, we will import the required modules from `electron`. These modules help
|
||||
control our application lifecycle and create a native browser window.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, BrowserWindow, shell } = require('electron')
|
||||
const path = require('node:path')
|
||||
```
|
||||
|
||||
Next, we will proceed to register our application to handle all "`electron-fiddle://`" protocols.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
|
||||
@@ -44,7 +44,7 @@ if (process.defaultApp) {
|
||||
|
||||
We will now define the function in charge of creating our browser window and load our application's `index.html` file.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
let mainWindow
|
||||
|
||||
const createWindow = () => {
|
||||
@@ -67,7 +67,7 @@ This code will be different in Windows and Linux compared to MacOS. This is due
|
||||
|
||||
#### Windows and Linux code:
|
||||
|
||||
```javascript @ts-type={mainWindow:Electron.BrowserWindow} @ts-type={createWindow:()=>void}
|
||||
```js @ts-type={mainWindow:Electron.BrowserWindow} @ts-type={createWindow:()=>void}
|
||||
const gotTheLock = app.requestSingleInstanceLock()
|
||||
|
||||
if (!gotTheLock) {
|
||||
@@ -92,7 +92,7 @@ if (!gotTheLock) {
|
||||
|
||||
#### MacOS code:
|
||||
|
||||
```javascript @ts-type={createWindow:()=>void}
|
||||
```js @ts-type={createWindow:()=>void}
|
||||
// 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.
|
||||
@@ -108,7 +108,7 @@ app.on('open-url', (event, url) => {
|
||||
|
||||
Finally, we will add some additional code to handle when someone closes our application.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
// 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.
|
||||
@@ -159,7 +159,7 @@ shows the bare minimum needed to add the configuration changes)_:
|
||||
}
|
||||
```
|
||||
|
||||
#### [Electron Packager](https://github.com/electron/electron-packager)
|
||||
#### [Electron Packager](https://github.com/electron/packager)
|
||||
|
||||
For macOS support:
|
||||
|
||||
@@ -167,8 +167,8 @@ If you're using Electron Packager's API, adding support for protocol handlers is
|
||||
Electron Forge is handled, except
|
||||
`protocols` is part of the Packager options passed to the `packager` function.
|
||||
|
||||
```javascript @ts-nocheck
|
||||
const packager = require('electron-packager')
|
||||
```js @ts-nocheck
|
||||
const packager = require('@electron/packager')
|
||||
|
||||
packager({
|
||||
// ...other options...
|
||||
|
||||
@@ -23,10 +23,10 @@ To set your custom dock menu, you need to use the
|
||||
[`app.dock.setMenu`](../api/dock.md#docksetmenumenu-macos) API,
|
||||
which is only available on macOS.
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/macos-dock-menu'
|
||||
const { app, BrowserWindow, Menu } = require('electron')
|
||||
```fiddle docs/fiddles/features/macos-dock-menu
|
||||
const { app, BrowserWindow, Menu } = require('electron/main')
|
||||
|
||||
const createWindow = () => {
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600
|
||||
|
||||
@@ -9,7 +9,7 @@ It is possible to use Node.js features in Electron's Web Workers, to do
|
||||
so the `nodeIntegrationInWorker` option should be set to `true` in
|
||||
`webPreferences`.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
nodeIntegrationInWorker: true
|
||||
@@ -42,7 +42,7 @@ safe.
|
||||
The only way to load a native module safely for now, is to make sure the app
|
||||
loads no native modules after the Web Workers get started.
|
||||
|
||||
```javascript @ts-expect-error=[1]
|
||||
```js @ts-expect-error=[1]
|
||||
process.dlopen = () => {
|
||||
throw new Error('Load native module is not safe')
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ Add a draggable element to `index.html`, and reference your renderer script:
|
||||
|
||||
In `renderer.js` set up the renderer process to handle drag events by calling the method you added via the [`contextBridge`][] above.
|
||||
|
||||
```javascript @ts-expect-error=[3]
|
||||
```js @ts-expect-error=[3]
|
||||
document.getElementById('drag').ondragstart = (event) => {
|
||||
event.preventDefault()
|
||||
window.electron.startDrag('drag-and-drop.md')
|
||||
@@ -56,15 +56,55 @@ document.getElementById('drag').ondragstart = (event) => {
|
||||
In the Main process (`main.js` file), expand the received event with a path to the file that is
|
||||
being dragged and an icon:
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/drag-and-drop'
|
||||
const { ipcMain } = require('electron')
|
||||
```fiddle docs/fiddles/features/drag-and-drop
|
||||
const { app, BrowserWindow, ipcMain } = require('electron/main')
|
||||
const path = require('node:path')
|
||||
const fs = require('node:fs')
|
||||
const https = require('node:https')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
const iconName = path.join(__dirname, 'iconForDragAndDrop.png')
|
||||
const icon = fs.createWriteStream(iconName)
|
||||
|
||||
// Create a new file to copy - you can also copy existing files.
|
||||
fs.writeFileSync(path.join(__dirname, 'drag-and-drop-1.md'), '# First file to test drag and drop')
|
||||
fs.writeFileSync(path.join(__dirname, 'drag-and-drop-2.md'), '# Second file to test drag and drop')
|
||||
|
||||
https.get('https://img.icons8.com/ios/452/drag-and-drop.png', (response) => {
|
||||
response.pipe(icon)
|
||||
})
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
ipcMain.on('ondragstart', (event, filePath) => {
|
||||
event.sender.startDrag({
|
||||
file: filePath,
|
||||
icon: '/path/to/icon.png'
|
||||
file: path.join(__dirname, filePath),
|
||||
icon: iconName
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
After launching the Electron application, try dragging and dropping
|
||||
|
||||
@@ -30,16 +30,38 @@ new Notification({
|
||||
|
||||
Here's a full example that you can open with Electron Fiddle:
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/notifications/main'
|
||||
const { Notification } = require('electron')
|
||||
```fiddle docs/fiddles/features/notifications/main
|
||||
const { app, BrowserWindow, Notification } = require('electron/main')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
const NOTIFICATION_TITLE = 'Basic Notification'
|
||||
const NOTIFICATION_BODY = 'Notification from the Main process'
|
||||
|
||||
new Notification({
|
||||
title: NOTIFICATION_TITLE,
|
||||
body: NOTIFICATION_BODY
|
||||
}).show()
|
||||
function showNotification () {
|
||||
new Notification({ title: NOTIFICATION_TITLE, body: NOTIFICATION_BODY }).show()
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow).then(showNotification)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Show notifications in the renderer process
|
||||
@@ -59,14 +81,13 @@ new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY }).onclick =
|
||||
|
||||
Here's a full example that you can open with Electron Fiddle:
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/notifications/renderer'
|
||||
```fiddle docs/fiddles/features/notifications/renderer|focus=renderer.js
|
||||
const NOTIFICATION_TITLE = 'Title'
|
||||
const NOTIFICATION_BODY =
|
||||
'Notification from the Renderer process. Click to log to console.'
|
||||
const CLICK_MESSAGE = 'Notification clicked'
|
||||
const NOTIFICATION_BODY = 'Notification from the Renderer process. Click to log to console.'
|
||||
const CLICK_MESSAGE = 'Notification clicked!'
|
||||
|
||||
new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY }).onclick =
|
||||
() => console.log(CLICK_MESSAGE)
|
||||
new window.Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY })
|
||||
.onclick = () => { document.getElementById('output').innerText = CLICK_MESSAGE }
|
||||
```
|
||||
|
||||
## Platform considerations
|
||||
|
||||
@@ -39,22 +39,44 @@ To enable this mode, GPU acceleration has to be disabled by calling the
|
||||
|
||||
## Example
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/offscreen-rendering'
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
```fiddle docs/fiddles/features/offscreen-rendering
|
||||
const { app, BrowserWindow } = require('electron/main')
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
|
||||
app.disableHardwareAcceleration()
|
||||
|
||||
let win
|
||||
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow({ webPreferences: { offscreen: true } })
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
offscreen: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadURL('https://github.com')
|
||||
win.webContents.on('paint', (event, dirty, image) => {
|
||||
fs.writeFileSync('ex.png', image.toPNG())
|
||||
})
|
||||
win.webContents.setFrameRate(60)
|
||||
console.log(`The screenshot has been successfully saved to ${path.join(process.cwd(), 'ex.png')}`)
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ careful to understand that the term "performance" means different things for
|
||||
a Node.js backend than it does for an application running on a client.
|
||||
|
||||
This list is provided for your convenience – and is, much like our
|
||||
[security checklist][security] – not meant to exhaustive. It is probably possible
|
||||
[security checklist][security] – not meant to be exhaustive. It is probably possible
|
||||
to build a slow Electron app that follows all the steps outlined below. Electron
|
||||
is a powerful development platform that enables you, the developer, to do more
|
||||
or less whatever you want. All that freedom means that performance is largely
|
||||
@@ -83,7 +83,7 @@ is not in fact the leanest or smallest one available.
|
||||
|
||||
The reasoning behind this recommendation is best illustrated with a real-world
|
||||
example. During the early days of Electron, reliable detection of network
|
||||
connectivity was a problem, resulting many apps to use a module that exposed a
|
||||
connectivity was a problem, resulting in many apps using a module that exposed a
|
||||
simple `isOnline()` method.
|
||||
|
||||
That module detected your network connectivity by attempting to reach out to a
|
||||
|
||||
@@ -83,7 +83,7 @@ terminated as well.
|
||||
|
||||
The main process also controls your application's lifecycle through Electron's
|
||||
[`app`][app] module. This module provides a large set of events and methods
|
||||
that you can use to add custom application behaviour (for instance, programmatically
|
||||
that you can use to add custom application behavior (for instance, programmatically
|
||||
quitting your application, modifying the application dock, or showing an About panel).
|
||||
|
||||
As a practical example, the app shown in the [quick start guide][quick-start-lifecycle]
|
||||
|
||||
@@ -50,12 +50,12 @@ See the [API documentation for more options and modes][setprogressbar].
|
||||
In this example, we add a progress bar to the main window that increments over time
|
||||
using Node.js timers.
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/progress-bar'
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
```fiddle docs/fiddles/features/progress-bar
|
||||
const { app, BrowserWindow } = require('electron/main')
|
||||
|
||||
let progressInterval
|
||||
|
||||
const createWindow = () => {
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600
|
||||
@@ -73,8 +73,11 @@ const createWindow = () => {
|
||||
win.setProgressBar(c)
|
||||
|
||||
// increment or reset progress bar
|
||||
if (c < 2) c += INCREMENT
|
||||
else c = 0
|
||||
if (c < 2) {
|
||||
c += INCREMENT
|
||||
} else {
|
||||
c = (-INCREMENT * 5) // reset to a bit less than 0 to show reset state
|
||||
}
|
||||
}, INTERVAL_DELAY)
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ need two Electron modules:
|
||||
windows.
|
||||
|
||||
Because the main process runs Node.js, you can import these as [CommonJS][commonjs]
|
||||
modules at the top of your file:
|
||||
modules at the top of your `main.js` file:
|
||||
|
||||
```js
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
@@ -24,12 +24,12 @@ the application via JumpList or dock menu, respectively.
|
||||
|
||||
### Managing recent documents
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/recent-documents'
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
```fiddle docs/fiddles/features/recent-documents
|
||||
const { app, BrowserWindow } = require('electron/main')
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
|
||||
const createWindow = () => {
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600
|
||||
@@ -116,7 +116,7 @@ following code snippet to your menu template:
|
||||
Make sure the application menu is added after the [`'ready'`](../api/app.md#event-ready)
|
||||
event and not before, or the menu item will be disabled:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, Menu } = require('electron')
|
||||
|
||||
const template = [
|
||||
|
||||
@@ -27,22 +27,30 @@ To set the represented file of window, you can use the
|
||||
|
||||
## Example
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/represented-file'
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
```fiddle docs/fiddles/features/represented-file
|
||||
const { app, BrowserWindow } = require('electron/main')
|
||||
const os = require('node:os')
|
||||
|
||||
const createWindow = () => {
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow()
|
||||
|
||||
win.setRepresentedFilename(os.homedir())
|
||||
win.setDocumentEdited(true)
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
@@ -50,12 +58,6 @@ app.on('window-all-closed', () => {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
After launching the Electron application, click on the title with `Command` or
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user