mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
186 Commits
v18.0.0-ni
...
v19.0.0-ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b888d9cd17 | ||
|
|
e589e9b259 | ||
|
|
86e746c36b | ||
|
|
ebfcf89a0b | ||
|
|
865a29ed17 | ||
|
|
373a905319 | ||
|
|
27527fe5ca | ||
|
|
e41c3e960d | ||
|
|
076bc58b2a | ||
|
|
b96f15bfc2 | ||
|
|
3bc3896ee7 | ||
|
|
a20216de7a | ||
|
|
a5a4818b67 | ||
|
|
aa8119515f | ||
|
|
3d9b9b97cf | ||
|
|
12aa991df2 | ||
|
|
0ff1727ec0 | ||
|
|
a1c01ded9c | ||
|
|
94a85cb191 | ||
|
|
f45aaea537 | ||
|
|
b43f7702c8 | ||
|
|
7beffb51fc | ||
|
|
3663f8e0ae | ||
|
|
41c81ed066 | ||
|
|
62366aeb95 | ||
|
|
89725f31bf | ||
|
|
f71a6db3ff | ||
|
|
c040305db4 | ||
|
|
d9bf02d9b6 | ||
|
|
318c91b78c | ||
|
|
ebd80a0602 | ||
|
|
306147ddf5 | ||
|
|
7cb62bfc22 | ||
|
|
283fa2b79d | ||
|
|
1e50f7d2b6 | ||
|
|
998c85af13 | ||
|
|
3da598015b | ||
|
|
c1a667c931 | ||
|
|
d5539ce834 | ||
|
|
067cc8ae2b | ||
|
|
c5a2af7811 | ||
|
|
8cf345660c | ||
|
|
da54cfcb3e | ||
|
|
268cd31e38 | ||
|
|
5b2d3910c1 | ||
|
|
08e26175fd | ||
|
|
41b2945ced | ||
|
|
bcf060fab6 | ||
|
|
e9b9835feb | ||
|
|
fa7461685d | ||
|
|
484a70f9b8 | ||
|
|
83a4ac1841 | ||
|
|
1e8da899a3 | ||
|
|
069cde09fb | ||
|
|
bdad6335c4 | ||
|
|
9d72c8b0ad | ||
|
|
faa392af28 | ||
|
|
683ff2ea02 | ||
|
|
9168f65321 | ||
|
|
101e17d6f3 | ||
|
|
b1463d2da1 | ||
|
|
36e730da93 | ||
|
|
e08ced5979 | ||
|
|
84cf685e76 | ||
|
|
fe43296f7f | ||
|
|
34129b83a4 | ||
|
|
b1777c5ad1 | ||
|
|
cc0eb7b908 | ||
|
|
c75ec2e689 | ||
|
|
600c37160b | ||
|
|
512bb96dcb | ||
|
|
90f17e4945 | ||
|
|
d36524c640 | ||
|
|
8397bfbd16 | ||
|
|
1e074605dc | ||
|
|
96c3179f32 | ||
|
|
8dfcf817e4 | ||
|
|
0a120468c0 | ||
|
|
4fa3310887 | ||
|
|
ceab6a146a | ||
|
|
cd7dc52c53 | ||
|
|
28ada6ea8b | ||
|
|
e9a43be9be | ||
|
|
254dbd7400 | ||
|
|
baaa7787af | ||
|
|
ac1d426c51 | ||
|
|
841d223b3b | ||
|
|
e119da8ce2 | ||
|
|
58af7d2a9a | ||
|
|
c09ce25ab6 | ||
|
|
ce86e81aa6 | ||
|
|
bf3650eb1f | ||
|
|
81fcd732c2 | ||
|
|
d46431b564 | ||
|
|
fb3f5e490e | ||
|
|
7442905dd2 | ||
|
|
2526031a5f | ||
|
|
e0f2511cba | ||
|
|
4c39eb32b0 | ||
|
|
c3d11e2ea2 | ||
|
|
ed185f324e | ||
|
|
9a5a45e804 | ||
|
|
8b6202b6a8 | ||
|
|
7c701367c0 | ||
|
|
56c6d25e98 | ||
|
|
b346f909e7 | ||
|
|
939bfa50f6 | ||
|
|
2289a52fb3 | ||
|
|
aeee9cfb78 | ||
|
|
e34d7f5d6f | ||
|
|
f5dc2a6535 | ||
|
|
365933f1f3 | ||
|
|
8e0e2d40e2 | ||
|
|
db9ab80694 | ||
|
|
32ae67c873 | ||
|
|
c6d061c2d4 | ||
|
|
d657cd8ed6 | ||
|
|
e693738f7c | ||
|
|
63908ccf89 | ||
|
|
3768a7b25f | ||
|
|
86f8faea6b | ||
|
|
20ed5701e9 | ||
|
|
16fcad3488 | ||
|
|
7caa88c46f | ||
|
|
cabad35383 | ||
|
|
8ec81c1437 | ||
|
|
7f517ba878 | ||
|
|
bac0a28324 | ||
|
|
4f6b8d06be | ||
|
|
8803e7f020 | ||
|
|
7814f96413 | ||
|
|
65bee9120f | ||
|
|
335f24b0d0 | ||
|
|
1cf36822e3 | ||
|
|
a0b7e30fe7 | ||
|
|
2f0d5651a9 | ||
|
|
2fe5d0e1e8 | ||
|
|
d26d337bb8 | ||
|
|
d1b48c0636 | ||
|
|
9d054755d6 | ||
|
|
7032be660d | ||
|
|
f5e138a5e3 | ||
|
|
11a8a296b5 | ||
|
|
6fb013fc10 | ||
|
|
87b3f6db9d | ||
|
|
6b41356868 | ||
|
|
d619804fc8 | ||
|
|
84e2460012 | ||
|
|
df50a0efb1 | ||
|
|
b89361a991 | ||
|
|
edfadda899 | ||
|
|
92bbac8ab6 | ||
|
|
4903d47ef3 | ||
|
|
ac0d6bdb1e | ||
|
|
6860429bf4 | ||
|
|
015d54ac10 | ||
|
|
b93f5fb066 | ||
|
|
0c75b3b2ea | ||
|
|
2a8d49a059 | ||
|
|
6e6f5efad9 | ||
|
|
fac61122d5 | ||
|
|
868794a6bd | ||
|
|
f75a274019 | ||
|
|
7f4efb6747 | ||
|
|
6c88e3b8e7 | ||
|
|
1aaa0fad69 | ||
|
|
ddd66543f7 | ||
|
|
f4548985f4 | ||
|
|
506d82a902 | ||
|
|
0a7bc4f5d1 | ||
|
|
de436f040f | ||
|
|
99ee1fc0eb | ||
|
|
cbe68bdbb8 | ||
|
|
2bbba9e242 | ||
|
|
94db8cd45e | ||
|
|
5d90ff083f | ||
|
|
cb927af455 | ||
|
|
d640260592 | ||
|
|
b0f315a637 | ||
|
|
483808a8cf | ||
|
|
746927c972 | ||
|
|
7c16ef1f62 | ||
|
|
ef058892bb | ||
|
|
bd861e5079 | ||
|
|
cb2c1f888e | ||
|
|
6d8a858897 |
@@ -45,18 +45,24 @@ executors:
|
||||
type: enum
|
||||
enum: ["medium", "xlarge", "2xlarge+"]
|
||||
docker:
|
||||
- image: ghcr.io/electron/build:27db4a3e3512bfd2e47f58cea69922da0835f1d9
|
||||
- image: ghcr.io/electron/build:e6bebd08a51a0d78ec23e5b3fd7e7c0846412328
|
||||
resource_class: << parameters.size >>
|
||||
|
||||
macos:
|
||||
parameters:
|
||||
size:
|
||||
description: "macOS executor size"
|
||||
default: large
|
||||
default: macos.x86.medium.gen2
|
||||
type: enum
|
||||
enum: ["medium", "large"]
|
||||
enum: ["macos.x86.medium.gen2", "large"]
|
||||
xcode:
|
||||
description: "xcode version"
|
||||
default: "12.4.0"
|
||||
type: enum
|
||||
enum: ["12.4.0", "13.2.1"]
|
||||
|
||||
macos:
|
||||
xcode: "12.4.0"
|
||||
xcode: << parameters.xcode >>
|
||||
resource_class: << parameters.size >>
|
||||
|
||||
# Electron Runners
|
||||
@@ -240,6 +246,12 @@ step-depot-tools-get: &step-depot-tools-get
|
||||
name: Get depot tools
|
||||
command: |
|
||||
git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
# remove ninjalog_uploader_wrapper.py from autoninja since we don't use it and it causes problems
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
sed -i '' '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
else
|
||||
sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
fi
|
||||
|
||||
step-depot-tools-add-to-path: &step-depot-tools-add-to-path
|
||||
run:
|
||||
@@ -343,10 +355,7 @@ step-get-more-space-on-mac: &step-get-more-space-on-mac
|
||||
command: |
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
sudo mkdir -p $TMPDIR/del-target
|
||||
if [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
# Remount the root volume as writable, don't ask questions plz
|
||||
sudo mount -uw /
|
||||
fi
|
||||
|
||||
tmpify() {
|
||||
if [ -d "$1" ]; then
|
||||
sudo mv "$1" $TMPDIR/del-target/$(echo $1|shasum -a 256|head -n1|cut -d " " -f1)
|
||||
@@ -388,33 +397,32 @@ step-get-more-space-on-mac: &step-get-more-space-on-mac
|
||||
tmpify /usr/local/Homebrew
|
||||
sudo rm -rf $TMPDIR/del-target
|
||||
|
||||
if [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
sudo rm -rf "/System/Library/Desktop Pictures"
|
||||
sudo rm -rf /System/Library/Templates/Data
|
||||
sudo rm -rf /System/Library/Speech/Voices
|
||||
sudo rm -rf "/System/Library/Screen Savers"
|
||||
sudo rm -rf /System/Volumes/Data/Library/Developer/CommandLineTools/SDKs
|
||||
sudo rm -rf "/System/Volumes/Data/Library/Application Support/Apple/Photos/Print Products"
|
||||
sudo rm -rf /System/Volumes/Data/Library/Java
|
||||
sudo rm -rf /System/Volumes/Data/Library/Ruby
|
||||
sudo rm -rf /System/Volumes/Data/Library/Printers
|
||||
sudo rm -rf /System/iOSSupport
|
||||
sudo rm -rf /System/Applications/*.app
|
||||
sudo rm -rf /System/Applications/Utilities/*.app
|
||||
sudo rm -rf /System/Library/LinguisticData
|
||||
sudo rm -rf /System/Volumes/Data/private/var/db/dyld/*
|
||||
# sudo rm -rf /System/Library/Fonts/*
|
||||
# sudo rm -rf /System/Library/PreferencePanes
|
||||
sudo rm -rf /System/Library/AssetsV2/*
|
||||
sudo rm -rf /Applications/Safari.app
|
||||
sudo rm -rf ~/project/src/build/linux
|
||||
sudo rm -rf ~/project/src/third_party/catapult/tracing/test_data
|
||||
sudo rm -rf ~/project/src/third_party/angle/third_party/VK-GL-CTS
|
||||
# sudo rm -rf "/System/Library/Desktop Pictures"
|
||||
# sudo rm -rf /System/Library/Templates/Data
|
||||
# sudo rm -rf /System/Library/Speech/Voices
|
||||
# sudo rm -rf "/System/Library/Screen Savers"
|
||||
# sudo rm -rf /System/Volumes/Data/Library/Developer/CommandLineTools/SDKs
|
||||
# sudo rm -rf "/System/Volumes/Data/Library/Application Support/Apple/Photos/Print Products"
|
||||
# sudo rm -rf /System/Volumes/Data/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/
|
||||
# sudo rm -rf /System/Volumes/Data/Library/Java
|
||||
# sudo rm -rf /System/Volumes/Data/Library/Ruby
|
||||
# sudo rm -rf /System/Volumes/Data/Library/Printers
|
||||
# sudo rm -rf /System/iOSSupport
|
||||
# sudo rm -rf /System/Applications/*.app
|
||||
# sudo rm -rf /System/Applications/Utilities/*.app
|
||||
# sudo rm -rf /System/Library/LinguisticData
|
||||
# sudo rm -rf /System/Volumes/Data/private/var/db/dyld/*
|
||||
# sudo rm -rf /System/Library/Fonts/*
|
||||
# sudo rm -rf /System/Library/PreferencePanes
|
||||
# sudo rm -rf /System/Library/AssetsV2/*
|
||||
sudo rm -rf /Applications/Safari.app
|
||||
sudo rm -rf ~/project/src/build/linux
|
||||
sudo rm -rf ~/project/src/third_party/catapult/tracing/test_data
|
||||
sudo rm -rf ~/project/src/third_party/angle/third_party/VK-GL-CTS
|
||||
|
||||
# lipo off some huge binaries arm64 versions to save space
|
||||
strip_arm_deep $(xcode-select -p)/../SharedFrameworks
|
||||
strip_arm_deep /System/Volumes/Data/Library/Developer/CommandLineTools/usr
|
||||
fi
|
||||
# lipo off some huge binaries arm64 versions to save space
|
||||
strip_arm_deep $(xcode-select -p)/../SharedFrameworks
|
||||
# strip_arm_deep /System/Volumes/Data/Library/Developer/CommandLineTools/usr
|
||||
fi
|
||||
background: true
|
||||
|
||||
@@ -455,10 +463,18 @@ step-fix-sync: &step-fix-sync
|
||||
# Fix Clang Install (wrong binary)
|
||||
rm -rf src/third_party/llvm-build
|
||||
python3 src/tools/clang/scripts/update.py
|
||||
|
||||
# Fix esbuild (wrong binary)
|
||||
echo 'infra/3pp/tools/esbuild/${platform}' `gclient getdep --deps-file=src/third_party/devtools-frontend/src/DEPS -r 'third_party/esbuild:infra/3pp/tools/esbuild/${platform}'` > esbuild_ensure_file
|
||||
cipd ensure --root src/third_party/devtools-frontend/src/third_party/esbuild -ensure-file esbuild_ensure_file
|
||||
fi
|
||||
|
||||
cd src/third_party/angle
|
||||
rm .git/objects/info/alternates
|
||||
git remote set-url origin https://chromium.googlesource.com/angle/angle.git
|
||||
cp .git/config .git/config.backup
|
||||
git remote remove origin
|
||||
mv .git/config.backup .git/config
|
||||
git fetch
|
||||
|
||||
step-install-signing-cert-on-mac: &step-install-signing-cert-on-mac
|
||||
@@ -884,12 +900,12 @@ step-touch-sync-done: &step-touch-sync-done
|
||||
step-maybe-restore-src-cache: &step-maybe-restore-src-cache
|
||||
restore_cache:
|
||||
keys:
|
||||
- v8-src-cache-{{ checksum "src/electron/.depshash" }}
|
||||
- v12-src-cache-{{ checksum "src/electron/.depshash" }}
|
||||
name: Restoring src cache
|
||||
step-maybe-restore-src-cache-marker: &step-maybe-restore-src-cache-marker
|
||||
restore_cache:
|
||||
keys:
|
||||
- v1-src-cache-marker-{{ checksum "src/electron/.depshash" }}
|
||||
- v5-src-cache-marker-{{ checksum "src/electron/.depshash" }}
|
||||
name: Restoring src cache marker
|
||||
|
||||
# Restore exact or closest git cache based on the hash of DEPS and .circle-sync-done
|
||||
@@ -898,10 +914,10 @@ step-maybe-restore-src-cache-marker: &step-maybe-restore-src-cache-marker
|
||||
step-maybe-restore-git-cache: &step-maybe-restore-git-cache
|
||||
restore_cache:
|
||||
paths:
|
||||
- ~/.gclient-cache
|
||||
- gclient-cache
|
||||
keys:
|
||||
- v2-gclient-cache-{{ checksum "src/electron/.circle-sync-done" }}-{{ checksum "src/electron/DEPS" }}
|
||||
- v2-gclient-cache-{{ checksum "src/electron/.circle-sync-done" }}
|
||||
- v5-gclient-cache-{{ checksum "src/electron/.circle-sync-done" }}-{{ checksum "src/electron/DEPS" }}
|
||||
- v5-gclient-cache-{{ checksum "src/electron/.circle-sync-done" }}
|
||||
name: Conditionally restoring git cache
|
||||
|
||||
step-restore-out-cache: &step-restore-out-cache
|
||||
@@ -918,15 +934,15 @@ step-set-git-cache-path: &step-set-git-cache-path
|
||||
command: |
|
||||
# CircleCI does not support interpolation when setting environment variables.
|
||||
# https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-shell-command
|
||||
echo 'export GIT_CACHE_PATH="$HOME/.gclient-cache"' >> $BASH_ENV
|
||||
echo 'export GIT_CACHE_PATH="$PWD/gclient-cache"' >> $BASH_ENV
|
||||
|
||||
# Persist the git cache based on the hash of DEPS and .circle-sync-done
|
||||
# If the src cache was restored above then this will persist an empty cache
|
||||
step-save-git-cache: &step-save-git-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- ~/.gclient-cache
|
||||
key: v2-gclient-cache-{{ checksum "src/electron/.circle-sync-done" }}-{{ checksum "src/electron/DEPS" }}
|
||||
- gclient-cache
|
||||
key: v5-gclient-cache-{{ checksum "src/electron/.circle-sync-done" }}-{{ checksum "src/electron/DEPS" }}
|
||||
name: Persisting git cache
|
||||
|
||||
step-save-out-cache: &step-save-out-cache
|
||||
@@ -971,7 +987,7 @@ step-save-src-cache: &step-save-src-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- /var/portal
|
||||
key: v8-src-cache-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
key: v12-src-cache-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
name: Persisting src cache
|
||||
step-make-src-cache-marker: &step-make-src-cache-marker
|
||||
run:
|
||||
@@ -981,7 +997,7 @@ step-save-src-cache-marker: &step-save-src-cache-marker
|
||||
save_cache:
|
||||
paths:
|
||||
- .src-cache-marker
|
||||
key: v1-src-cache-marker-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
key: v5-src-cache-marker-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
|
||||
step-maybe-early-exit-no-doc-change: &step-maybe-early-exit-no-doc-change
|
||||
run:
|
||||
@@ -1346,10 +1362,6 @@ commands:
|
||||
- *step-gclient-sync
|
||||
- store_artifacts:
|
||||
path: patches
|
||||
- when:
|
||||
condition: << parameters.save-git-cache >>
|
||||
steps:
|
||||
- *step-save-git-cache
|
||||
# These next few steps reset Electron to the correct commit regardless of which cache was restored
|
||||
- run:
|
||||
name: Wipe Electron
|
||||
@@ -1358,6 +1370,11 @@ commands:
|
||||
- *step-run-electron-only-hooks
|
||||
- *step-generate-deps-hash-cleanly
|
||||
- *step-mark-sync-done
|
||||
# Save git cache AFTER sync marked done because other jobs expect that to be the case
|
||||
- when:
|
||||
condition: << parameters.save-git-cache >>
|
||||
steps:
|
||||
- *step-save-git-cache
|
||||
- *step-minimize-workspace-size-from-checkout
|
||||
- *step-delete-git-directories
|
||||
- when:
|
||||
@@ -1535,12 +1552,11 @@ commands:
|
||||
jobs:
|
||||
# Layer 0: Docs. Standalone.
|
||||
ts-compile-doc-change:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: medium
|
||||
executor: linux-docker
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *env-linux-2xlarge
|
||||
<<: *env-testing-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-electron-ts-compile-for-doc-change
|
||||
|
||||
# Layer 1: Checkout.
|
||||
@@ -1885,7 +1901,9 @@ jobs:
|
||||
checkout: true
|
||||
|
||||
osx-testing-x64:
|
||||
executor: macos
|
||||
executor:
|
||||
name: macos
|
||||
xcode: "13.2.1"
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-testing-build
|
||||
@@ -1902,14 +1920,16 @@ jobs:
|
||||
osx-testing-x64-gn-check:
|
||||
executor:
|
||||
name: macos
|
||||
size: medium
|
||||
xcode: "13.2.1"
|
||||
environment:
|
||||
<<: *env-machine-mac
|
||||
<<: *env-testing-build
|
||||
<<: *steps-electron-gn-check
|
||||
|
||||
osx-publish-x64-skip-checkout:
|
||||
executor: macos
|
||||
executor:
|
||||
name: macos
|
||||
xcode: "13.2.1"
|
||||
environment:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-release-build
|
||||
@@ -1928,7 +1948,9 @@ jobs:
|
||||
checkout: false
|
||||
|
||||
osx-publish-arm64-skip-checkout:
|
||||
executor: macos
|
||||
executor:
|
||||
name: macos
|
||||
xcode: "13.2.1"
|
||||
environment:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-release-build
|
||||
@@ -1948,7 +1970,9 @@ jobs:
|
||||
checkout: false
|
||||
|
||||
osx-testing-arm64:
|
||||
executor: macos
|
||||
executor:
|
||||
name: macos
|
||||
xcode: "13.2.1"
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-testing-build
|
||||
@@ -1965,7 +1989,9 @@ jobs:
|
||||
attach: true
|
||||
|
||||
mas-testing-x64:
|
||||
executor: macos
|
||||
executor:
|
||||
name: macos
|
||||
xcode: "13.2.1"
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-mas
|
||||
@@ -1983,7 +2009,7 @@ jobs:
|
||||
mas-testing-x64-gn-check:
|
||||
executor:
|
||||
name: macos
|
||||
size: medium
|
||||
xcode: "13.2.1"
|
||||
environment:
|
||||
<<: *env-machine-mac
|
||||
<<: *env-mas
|
||||
@@ -1991,7 +2017,9 @@ jobs:
|
||||
<<: *steps-electron-gn-check
|
||||
|
||||
mas-publish-x64-skip-checkout:
|
||||
executor: macos
|
||||
executor:
|
||||
name: macos
|
||||
xcode: "13.2.1"
|
||||
environment:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-mas
|
||||
@@ -2010,7 +2038,9 @@ jobs:
|
||||
checkout: false
|
||||
|
||||
mas-publish-arm64-skip-checkout:
|
||||
executor: macos
|
||||
executor:
|
||||
name: macos
|
||||
xcode: "13.2.1"
|
||||
environment:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-mas-apple-silicon
|
||||
@@ -2030,7 +2060,9 @@ jobs:
|
||||
checkout: false
|
||||
|
||||
mas-testing-arm64:
|
||||
executor: macos
|
||||
executor:
|
||||
name: macos
|
||||
xcode: "13.2.1"
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-testing-build
|
||||
@@ -2217,9 +2249,7 @@ jobs:
|
||||
<<: *steps-tests
|
||||
|
||||
osx-testing-x64-tests:
|
||||
executor:
|
||||
name: macos
|
||||
size: medium
|
||||
executor: macos
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
@@ -2235,9 +2265,7 @@ jobs:
|
||||
<<: *steps-tests
|
||||
|
||||
mas-testing-x64-tests:
|
||||
executor:
|
||||
name: macos
|
||||
size: medium
|
||||
executor: macos
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
|
||||
5
.git-blame-ignore-revs
Normal file
5
.git-blame-ignore-revs
Normal file
@@ -0,0 +1,5 @@
|
||||
# Atom --> Electron rename
|
||||
d9321f4df751fa32813fab1b6387bbd61bd681d0
|
||||
34c4c8d5088fa183f56baea28809de6f2a427e02
|
||||
# Enable JS Semicolons
|
||||
5d657dece4102e5e5304d42e8004b6ad64c0fcda
|
||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -4,7 +4,7 @@
|
||||
# https://git-scm.com/docs/gitignore
|
||||
|
||||
# Upgrades WG
|
||||
/patches/ @electron/wg-upgrades
|
||||
/patches/ @electron/wg-upgrades @electron/wg-security
|
||||
DEPS @electron/wg-upgrades
|
||||
|
||||
# Releases WG
|
||||
|
||||
44
BUILD.gn
44
BUILD.gn
@@ -361,6 +361,7 @@ source_set("electron_lib") {
|
||||
"//components/network_hints/common:mojo_bindings",
|
||||
"//components/network_hints/renderer",
|
||||
"//components/network_session_configurator/common",
|
||||
"//components/omnibox/browser:buildflags",
|
||||
"//components/os_crypt",
|
||||
"//components/pref_registry",
|
||||
"//components/prefs",
|
||||
@@ -472,8 +473,8 @@ source_set("electron_lib") {
|
||||
|
||||
if (is_linux) {
|
||||
deps += [
|
||||
"//build/config/linux/gtk:gtkprint",
|
||||
"//components/crash/content/browser",
|
||||
"//ui/gtk:gtk_config",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -501,6 +502,8 @@ source_set("electron_lib") {
|
||||
"StoreKit.framework",
|
||||
]
|
||||
|
||||
weak_frameworks = [ "QuickLookThumbnailing.framework" ]
|
||||
|
||||
sources += [
|
||||
"shell/browser/ui/views/autofill_popup_view.cc",
|
||||
"shell/browser/ui/views/autofill_popup_view.h",
|
||||
@@ -549,13 +552,14 @@ source_set("electron_lib") {
|
||||
sources += filenames.lib_sources_linux_x11
|
||||
public_deps += [
|
||||
"//ui/base/x",
|
||||
"//ui/platform_window/x11",
|
||||
"//ui/ozone/platform/x11",
|
||||
]
|
||||
}
|
||||
configs += [ ":gio_unix" ]
|
||||
defines += [
|
||||
# Disable warnings for g_settings_list_schemas.
|
||||
"GLIB_DISABLE_DEPRECATION_WARNINGS",
|
||||
"USE_X11=1",
|
||||
]
|
||||
|
||||
sources += [
|
||||
@@ -899,8 +903,12 @@ if (is_mac) {
|
||||
deps += [ "//sandbox/mac:seatbelt" ]
|
||||
}
|
||||
defines = [ "HELPER_EXECUTABLE" ]
|
||||
sources = filenames.app_sources
|
||||
sources += [ "shell/common/electron_constants.cc" ]
|
||||
sources = [
|
||||
"shell/app/electron_main_mac.cc",
|
||||
"shell/app/uv_stdio_fix.cc",
|
||||
"shell/app/uv_stdio_fix.h",
|
||||
"shell/common/electron_constants.cc",
|
||||
]
|
||||
include_dirs = [ "." ]
|
||||
info_plist = "shell/renderer/resources/mac/Info.plist"
|
||||
extra_substitutions =
|
||||
@@ -1039,15 +1047,18 @@ if (is_mac) {
|
||||
|
||||
mac_app_bundle("electron_app") {
|
||||
output_name = electron_product_name
|
||||
sources = filenames.app_sources
|
||||
sources += [ "shell/common/electron_constants.cc" ]
|
||||
sources = [
|
||||
"shell/app/electron_main_mac.cc",
|
||||
"shell/app/uv_stdio_fix.cc",
|
||||
"shell/app/uv_stdio_fix.h",
|
||||
"shell/common/electron_constants.cc",
|
||||
]
|
||||
include_dirs = [ "." ]
|
||||
deps = [
|
||||
":electron_app_framework_bundle_data",
|
||||
":electron_app_plist",
|
||||
":electron_app_resources",
|
||||
":electron_fuses",
|
||||
"//base",
|
||||
"//electron/buildflags",
|
||||
]
|
||||
if (is_mas_build) {
|
||||
@@ -1149,7 +1160,15 @@ if (is_mac) {
|
||||
|
||||
executable("electron_app") {
|
||||
output_name = electron_project_name
|
||||
sources = filenames.app_sources
|
||||
if (is_win) {
|
||||
sources = [ "shell/app/electron_main_win.cc" ]
|
||||
} else if (is_linux) {
|
||||
sources = [
|
||||
"shell/app/electron_main_linux.cc",
|
||||
"shell/app/uv_stdio_fix.cc",
|
||||
"shell/app/uv_stdio_fix.h",
|
||||
]
|
||||
}
|
||||
include_dirs = [ "." ]
|
||||
deps = [
|
||||
":default_app_asar",
|
||||
@@ -1170,7 +1189,7 @@ if (is_mac) {
|
||||
if (enable_hidpi) {
|
||||
data += [ "$root_out_dir/chrome_200_percent.pak" ]
|
||||
}
|
||||
foreach(locale, locales) {
|
||||
foreach(locale, platform_pak_locales) {
|
||||
data += [ "$root_out_dir/locales/$locale.pak" ]
|
||||
}
|
||||
|
||||
@@ -1385,11 +1404,13 @@ dist_zip("electron_dist_zip") {
|
||||
if (is_linux) {
|
||||
data_deps += [ "//sandbox/linux:chrome_sandbox" ]
|
||||
}
|
||||
deps = data_deps
|
||||
outputs = [ "$root_build_dir/dist.zip" ]
|
||||
}
|
||||
|
||||
dist_zip("electron_ffmpeg_zip") {
|
||||
data_deps = [ "//third_party/ffmpeg" ]
|
||||
deps = data_deps
|
||||
outputs = [ "$root_build_dir/ffmpeg.zip" ]
|
||||
}
|
||||
|
||||
@@ -1407,6 +1428,7 @@ group("electron_chromedriver") {
|
||||
dist_zip("electron_chromedriver_zip") {
|
||||
testonly = true
|
||||
data_deps = electron_chromedriver_deps
|
||||
deps = data_deps
|
||||
outputs = [ "$root_build_dir/chromedriver.zip" ]
|
||||
}
|
||||
|
||||
@@ -1425,6 +1447,7 @@ group("electron_mksnapshot") {
|
||||
|
||||
dist_zip("electron_mksnapshot_zip") {
|
||||
data_deps = mksnapshot_deps
|
||||
deps = data_deps
|
||||
outputs = [ "$root_build_dir/mksnapshot.zip" ]
|
||||
}
|
||||
|
||||
@@ -1435,6 +1458,7 @@ copy("hunspell_dictionaries") {
|
||||
|
||||
dist_zip("hunspell_dictionaries_zip") {
|
||||
data_deps = [ ":hunspell_dictionaries" ]
|
||||
deps = data_deps
|
||||
flatten = true
|
||||
|
||||
outputs = [ "$root_build_dir/hunspell_dictionaries.zip" ]
|
||||
@@ -1448,6 +1472,7 @@ copy("libcxx_headers") {
|
||||
|
||||
dist_zip("libcxx_headers_zip") {
|
||||
data_deps = [ ":libcxx_headers" ]
|
||||
deps = data_deps
|
||||
flatten = true
|
||||
flatten_relative_to = rebase_path(
|
||||
"$target_gen_dir/electron_libcxx_include/buildtools/third_party/libc++/trunk",
|
||||
@@ -1463,6 +1488,7 @@ copy("libcxxabi_headers") {
|
||||
|
||||
dist_zip("libcxxabi_headers_zip") {
|
||||
data_deps = [ ":libcxxabi_headers" ]
|
||||
deps = data_deps
|
||||
flatten = true
|
||||
flatten_relative_to = rebase_path(
|
||||
"$target_gen_dir/electron_libcxxabi_include/buildtools/third_party/libc++abi/trunk",
|
||||
|
||||
4
DEPS
4
DEPS
@@ -15,9 +15,9 @@ gclient_gn_args = [
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'98.0.4706.0',
|
||||
'100.0.4894.0',
|
||||
'node_version':
|
||||
'v16.13.1',
|
||||
'v16.13.2',
|
||||
'nan_version':
|
||||
# The following commit hash of NAN is v2.14.2 with *only* changes to the
|
||||
# test suite. This should be updated to a specific tag when one becomes
|
||||
|
||||
@@ -1 +1 @@
|
||||
18.0.0-nightly.20220107
|
||||
19.0.0-nightly.20220310
|
||||
35
README.md
35
README.md
@@ -34,6 +34,17 @@ For more installation options and troubleshooting tips, see
|
||||
[installation](docs/tutorial/installation.md). For info on how to manage Electron versions in your apps, see
|
||||
[Electron versioning](docs/tutorial/electron-versioning.md).
|
||||
|
||||
## Platform support
|
||||
|
||||
Each Electron release provides binaries for macOS, Windows, and Linux.
|
||||
|
||||
* macOS (El Capitan and up): Electron provides 64-bit Intel and ARM binaries for macOS. Apple Silicon support was added in Electron 11.
|
||||
* Windows (Windows 7 and up): Electron provides `ia32` (`x86`), `x64` (`amd64`), and `arm64` binaries for Windows. Windows on ARM support was added in Electron 5.0.8.
|
||||
* Linux: The prebuilt binaries of Electron are built on Ubuntu 18.04. They have also been verified to work on:
|
||||
* Ubuntu 14.04 and newer
|
||||
* Fedora 24 and newer
|
||||
* Debian 8 and newer
|
||||
|
||||
## Quick start & Electron Fiddle
|
||||
|
||||
Use [`Electron Fiddle`](https://github.com/electron/fiddle)
|
||||
@@ -54,12 +65,10 @@ npm start
|
||||
|
||||
## Resources for learning Electron
|
||||
|
||||
- [electronjs.org/docs](https://electronjs.org/docs) - All of Electron's documentation
|
||||
- [electron/fiddle](https://github.com/electron/fiddle) - A tool to build, run, and package small Electron experiments
|
||||
- [electron/electron-quick-start](https://github.com/electron/electron-quick-start) - A very basic starter Electron app
|
||||
- [electronjs.org/community#boilerplates](https://electronjs.org/community#boilerplates) - Sample starter apps created by the community
|
||||
- [electron/simple-samples](https://github.com/electron/simple-samples) - Small applications with ideas for taking them further
|
||||
- [electron/electron-api-demos](https://github.com/electron/electron-api-demos) - An Electron app that teaches you how to use Electron
|
||||
* [electronjs.org/docs](https://electronjs.org/docs) - All of Electron's documentation
|
||||
* [electron/fiddle](https://github.com/electron/fiddle) - A tool to build, run, and package small Electron experiments
|
||||
* [electron/electron-quick-start](https://github.com/electron/electron-quick-start) - A very basic starter Electron app
|
||||
* [electronjs.org/community#boilerplates](https://electronjs.org/community#boilerplates) - Sample starter apps created by the community
|
||||
|
||||
## Programmatic usage
|
||||
|
||||
@@ -80,11 +89,15 @@ const child = proc.spawn(electron)
|
||||
|
||||
### Mirrors
|
||||
|
||||
- [China](https://npmmirror.com/mirrors/electron)
|
||||
* [China](https://npm.taobao.org/mirrors/electron)
|
||||
|
||||
## Documentation Translations
|
||||
See the [Advanced Installation Instructions](https://www.electronjs.org/docs/latest/tutorial/installation#mirror) to learn how to use a custom mirror.
|
||||
|
||||
Find documentation translations in [electron/i18n](https://github.com/electron/i18n).
|
||||
## Documentation translations
|
||||
|
||||
We crowdsource translations for our documentation via [Crowdin](https://crowdin.com/project/electron).
|
||||
We currently accept translations for Chinese (Simplified), French, German, Japanese, Portuguese,
|
||||
Russian, and Spanish.
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -93,10 +106,10 @@ If you are interested in reporting/fixing issues and contributing directly to th
|
||||
## Community
|
||||
|
||||
Info on reporting bugs, getting help, finding third-party tools and sample apps,
|
||||
and more can be found in the [support document](docs/tutorial/support.md#finding-support).
|
||||
and more can be found on the [Community page](https://www.electronjs.org/community).
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/electron/electron/blob/main/LICENSE)
|
||||
|
||||
When using the Electron or other GitHub logos, be sure to follow the [GitHub logo guidelines](https://github.com/logos).
|
||||
When using Electron logos, make sure to follow [OpenJS Foundation Trademark Policy](https://openjsf.org/wp-content/uploads/sites/84/2021/01/OpenJS-Foundation-Trademark-Policy-2021-01-12.docx.pdf).
|
||||
|
||||
@@ -34,6 +34,7 @@ environment:
|
||||
GIT_CACHE_PATH: C:\Users\electron\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
ELECTRON_ALSO_LOG_TO_STDERR: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
@@ -209,7 +210,9 @@ test_script:
|
||||
}
|
||||
- cd electron
|
||||
# CalculateNativeWinOcclusion is disabled due to https://bugs.chromium.org/p/chromium/issues/detail?id=1139022
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running test suite & node script/yarn test -- --trace-uncaught --enable-logging --disable-features=CalculateNativeWinOcclusion )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running main test suite & node script/yarn test -- --trace-uncaught --runners=main --enable-logging=file --log-file=%cd%\electron.log --disable-features=CalculateNativeWinOcclusion )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running remote test suite & node script/yarn test -- --trace-uncaught --runners=remote --runTestFilesSeperately --enable-logging=file --log-file=%cd%\electron.log --disable-features=CalculateNativeWinOcclusion )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running native test suite & node script/yarn test -- --trace-uncaught --runners=native --enable-logging=file --log-file=%cd%\electron.log --disable-features=CalculateNativeWinOcclusion )
|
||||
- cd ..
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
|
||||
- echo "About to verify mksnapshot"
|
||||
@@ -217,6 +220,7 @@ test_script:
|
||||
- echo "Done verifying mksnapshot"
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying chromedriver & python electron\script\verify-chromedriver.py --build-dir out\Default --source-root %cd% )
|
||||
- echo "Done verifying chromedriver"
|
||||
- if exist %cd%\electron.log ( appveyor-retry appveyor PushArtifact %cd%\electron.log )
|
||||
deploy_script:
|
||||
- cd electron
|
||||
- ps: >-
|
||||
@@ -231,3 +235,5 @@ deploy_script:
|
||||
} elseif (Test-Path Env:\TEST_WOA) {
|
||||
node script/release/ci-release-build.js --job=electron-woa-testing --ci=VSTS --armTest --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH
|
||||
}
|
||||
on_finish:
|
||||
- if exist src\electron\electron.log ( appveyor-retry appveyor PushArtifact src\electron\electron.log )
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy Files to: src\electron'
|
||||
inputs:
|
||||
TargetFolder: src\electron
|
||||
- checkout: self
|
||||
path: src\electron
|
||||
|
||||
- script: |
|
||||
cd src\electron
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
displayName: 'Yarn install'
|
||||
|
||||
@@ -13,13 +13,13 @@ steps:
|
||||
$localArtifactPath = "$pwd\dist.zip"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/dist.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -osrc\out\Default -y $localArtifactPath
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -o$(Pipeline.Workspace)\src\out\Default -y $localArtifactPath
|
||||
displayName: 'Download and extract dist.zip for test'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$pwd\src\out\Default\shell_browser_ui_unittests.exe"
|
||||
$localArtifactPath = "$(Pipeline.Workspace)\src\out\Default\shell_browser_ui_unittests.exe"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/shell_browser_ui_unittests.exe"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
displayName: 'Download and extract native test executables for test'
|
||||
@@ -30,56 +30,57 @@ steps:
|
||||
$localArtifactPath = "$pwd\ffmpeg.zip"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/ffmpeg.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -osrc\out\ffmpeg $localArtifactPath
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -o$(Pipeline.Workspace)\src\out\ffmpeg $localArtifactPath
|
||||
displayName: 'Download and extract ffmpeg.zip for test'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$pwd\src\node_headers.zip"
|
||||
$localArtifactPath = "$(Pipeline.Workspace)\src\node_headers.zip"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/node_headers.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
cd src
|
||||
cd $(Pipeline.Workspace)\src
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y node_headers.zip
|
||||
displayName: 'Download node headers for test'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$pwd\src\out\Default\electron.lib"
|
||||
$localArtifactPath = "$(Pipeline.Workspace)\src\out\Default\electron.lib"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/electron.lib"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
displayName: 'Download electron.lib for test'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
try {
|
||||
$localArtifactPath = "$pwd\src\pdb.zip"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/pdb.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
cd src
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y pdb.zip
|
||||
} catch {
|
||||
Write-Host "There was an exception encountered while downloading pdb files:" $_.Exception.Message
|
||||
} finally {
|
||||
$global:LASTEXITCODE = 0
|
||||
}
|
||||
displayName: 'Download pdb files for detailed stacktraces'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
# Uncomment the following block if pdb files are needed to debug issues
|
||||
# - powershell: |
|
||||
# try {
|
||||
# $localArtifactPath = "$(Pipeline.Workspace)\src\pdb.zip"
|
||||
# $serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/pdb.zip"
|
||||
# Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
# cd $(Pipeline.Workspace)\src
|
||||
# & "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y pdb.zip
|
||||
# } catch {
|
||||
# Write-Host "There was an exception encountered while downloading pdb files:" $_.Exception.Message
|
||||
# } finally {
|
||||
# $global:LASTEXITCODE = 0
|
||||
# }
|
||||
# displayName: 'Download pdb files for detailed stacktraces'
|
||||
# env:
|
||||
# APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
New-Item src\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path src\out\Default\electron.lib -destination src\out\Default\gen\node_headers\Release\node.lib
|
||||
New-Item $(Pipeline.Workspace)\src\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path $(Pipeline.Workspace)\src\out\Default\electron.lib -destination $(Pipeline.Workspace)\src\out\Default\gen\node_headers\Release\node.lib
|
||||
displayName: 'Setup node headers'
|
||||
|
||||
- script: |
|
||||
cd src
|
||||
cd $(Pipeline.Workspace)\src
|
||||
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
node script/yarn test --runners=main --runTestFilesSeperately --enable-logging --disable-features=CalculateNativeWinOcclusion
|
||||
node script/yarn test --runners=main --enable-logging --disable-features=CalculateNativeWinOcclusion
|
||||
displayName: 'Run Electron Main process tests'
|
||||
env:
|
||||
ELECTRON_ENABLE_STACK_DUMPING: true
|
||||
@@ -90,7 +91,7 @@ steps:
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
|
||||
- script: |
|
||||
cd src
|
||||
cd $(Pipeline.Workspace)\src
|
||||
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
@@ -102,17 +103,17 @@ steps:
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
condition: always()
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish Test Results'
|
||||
inputs:
|
||||
testResultsFiles: '*.xml'
|
||||
searchFolder: '$(System.DefaultWorkingDirectory)/src/junit/'
|
||||
searchFolder: '$(Pipeline.Workspace)/src/junit/'
|
||||
condition: always()
|
||||
|
||||
- script: |
|
||||
cd src
|
||||
cd $(Pipeline.Workspace)\src
|
||||
echo "Verifying non proprietary ffmpeg"
|
||||
python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
|
||||
displayName: 'Verify ffmpeg'
|
||||
|
||||
@@ -2,7 +2,7 @@ is_electron_build = true
|
||||
root_extra_deps = [ "//electron" ]
|
||||
|
||||
# Registry of NMVs --> https://github.com/nodejs/node/blob/master/doc/abi_version_registry.json
|
||||
node_module_version = 103
|
||||
node_module_version = 106
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_typed_array_max_size_in_heap = 0
|
||||
@@ -14,6 +14,9 @@ v8_enable_snapshot_native_code_counters = false
|
||||
# TODO(codebytere): remove when Node.js handles https://chromium-review.googlesource.com/c/v8/v8/+/3211575
|
||||
v8_scriptormodule_legacy_lifetime = true
|
||||
|
||||
# we use this api
|
||||
v8_enable_javascript_promise_hooks = true
|
||||
|
||||
enable_cdm_host_verification = false
|
||||
proprietary_codecs = true
|
||||
ffmpeg_branding = "Chrome"
|
||||
|
||||
@@ -53,8 +53,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/predictors/resolve_host_client_impl.cc",
|
||||
"//chrome/browser/predictors/resolve_host_client_impl.h",
|
||||
"//chrome/browser/process_singleton.h",
|
||||
"//chrome/browser/ui/browser_dialogs.cc",
|
||||
"//chrome/browser/ui/browser_dialogs.h",
|
||||
"//chrome/browser/process_singleton_internal.cc",
|
||||
"//chrome/browser/process_singleton_internal.h",
|
||||
"//chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.cc",
|
||||
"//chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h",
|
||||
"//chrome/browser/ui/exclusive_access/exclusive_access_controller_base.cc",
|
||||
@@ -140,10 +140,6 @@ static_library("chrome") {
|
||||
"//components/optimization_guide/proto:optimization_guide_proto",
|
||||
]
|
||||
|
||||
if (enable_basic_printing && is_win) {
|
||||
deps += [ "//chrome/common:cloud_print_utility_mojom" ]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
sources += [ "//chrome/browser/icon_loader_auralinux.cc" ]
|
||||
if (use_ozone) {
|
||||
@@ -199,12 +195,16 @@ static_library("chrome") {
|
||||
|
||||
if (enable_basic_printing) {
|
||||
sources += [
|
||||
"//chrome/browser/bad_message.cc",
|
||||
"//chrome/browser/bad_message.h",
|
||||
"//chrome/browser/printing/print_job.cc",
|
||||
"//chrome/browser/printing/print_job.h",
|
||||
"//chrome/browser/printing/print_job_manager.cc",
|
||||
"//chrome/browser/printing/print_job_manager.h",
|
||||
"//chrome/browser/printing/print_job_worker.cc",
|
||||
"//chrome/browser/printing/print_job_worker.h",
|
||||
"//chrome/browser/printing/print_job_worker_oop.cc",
|
||||
"//chrome/browser/printing/print_job_worker_oop.h",
|
||||
"//chrome/browser/printing/print_view_manager_base.cc",
|
||||
"//chrome/browser/printing/print_view_manager_base.h",
|
||||
"//chrome/browser/printing/printer_query.cc",
|
||||
@@ -239,8 +239,6 @@ static_library("chrome") {
|
||||
sources += [
|
||||
"//chrome/browser/printing/pdf_to_emf_converter.cc",
|
||||
"//chrome/browser/printing/pdf_to_emf_converter.h",
|
||||
"//chrome/utility/printing_handler.cc",
|
||||
"//chrome/utility/printing_handler.h",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -255,8 +253,12 @@ static_library("chrome") {
|
||||
"//chrome/browser/ui/views/overlay/close_image_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/close_image_button.h",
|
||||
"//chrome/browser/ui/views/overlay/constants.h",
|
||||
"//chrome/browser/ui/views/overlay/document_overlay_window_views.cc",
|
||||
"//chrome/browser/ui/views/overlay/document_overlay_window_views.h",
|
||||
"//chrome/browser/ui/views/overlay/hang_up_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/hang_up_button.h",
|
||||
"//chrome/browser/ui/views/overlay/overlay_window_image_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/overlay_window_image_button.h",
|
||||
"//chrome/browser/ui/views/overlay/overlay_window_views.cc",
|
||||
"//chrome/browser/ui/views/overlay/overlay_window_views.h",
|
||||
"//chrome/browser/ui/views/overlay/playback_image_button.cc",
|
||||
@@ -271,11 +273,14 @@ static_library("chrome") {
|
||||
"//chrome/browser/ui/views/overlay/toggle_microphone_button.h",
|
||||
"//chrome/browser/ui/views/overlay/track_image_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/track_image_button.h",
|
||||
"//chrome/browser/ui/views/overlay/video_overlay_window_views.cc",
|
||||
"//chrome/browser/ui/views/overlay/video_overlay_window_views.h",
|
||||
]
|
||||
|
||||
deps += [
|
||||
"//chrome/app/vector_icons",
|
||||
"//components/vector_icons:vector_icons",
|
||||
"//ui/views/controls/webview",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -295,6 +300,8 @@ static_library("chrome") {
|
||||
sources += [
|
||||
"//chrome/browser/pdf/pdf_extension_util.cc",
|
||||
"//chrome/browser/pdf/pdf_extension_util.h",
|
||||
"//chrome/browser/pdf/pdf_frame_util.cc",
|
||||
"//chrome/browser/pdf/pdf_frame_util.h",
|
||||
"//chrome/renderer/pepper/chrome_pdf_print_client.cc",
|
||||
"//chrome/renderer/pepper/chrome_pdf_print_client.h",
|
||||
]
|
||||
|
||||
@@ -92,7 +92,7 @@ function loadApplicationPackage (packagePath: string) {
|
||||
try {
|
||||
packageJson = require(packageJsonPath);
|
||||
} catch (e) {
|
||||
showErrorMessage(`Unable to parse ${packageJsonPath}\n\n${e.message}`);
|
||||
showErrorMessage(`Unable to parse ${packageJsonPath}\n\n${(e as Error).message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ function loadApplicationPackage (packagePath: string) {
|
||||
const filePath = Module._resolveFilename(packagePath, module, true);
|
||||
app.setAppPath(appPath || path.dirname(filePath));
|
||||
} catch (e) {
|
||||
showErrorMessage(`Unable to find Electron app at ${packagePath}\n\n${e.message}`);
|
||||
showErrorMessage(`Unable to find Electron app at ${packagePath}\n\n${(e as Error).message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ function loadApplicationPackage (packagePath: string) {
|
||||
Module._load(packagePath, module, true);
|
||||
} catch (e) {
|
||||
console.error('App threw an error during load');
|
||||
console.error(e.stack || e);
|
||||
console.error((e as Error).stack || e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,6 @@ an issue:
|
||||
* [Automated Testing](tutorial/automated-testing.md)
|
||||
* [REPL](tutorial/repl.md)
|
||||
* [Distribution](tutorial/application-distribution.md)
|
||||
* [Supported Platforms](tutorial/support.md#supported-platforms)
|
||||
* [Code Signing](tutorial/code-signing.md)
|
||||
* [Mac App Store](tutorial/mac-app-store-submission-guide.md)
|
||||
* [Windows Store](tutorial/windows-store-guide.md)
|
||||
|
||||
@@ -484,6 +484,7 @@ Returns:
|
||||
* `argv` string[] - An array of the second instance's command line arguments
|
||||
* `workingDirectory` string - The second instance's working directory
|
||||
* `additionalData` unknown - A JSON object of additional data passed from the second instance
|
||||
* `ackCallback` unknown - A function that can be used to send data back to the second instance
|
||||
|
||||
This event will be emitted inside the primary instance of your application
|
||||
when a second instance has been executed and calls `app.requestSingleInstanceLock()`.
|
||||
@@ -495,12 +496,35 @@ non-minimized.
|
||||
|
||||
**Note:** If the second instance is started by a different user than the first, the `argv` array will not include the arguments.
|
||||
|
||||
**Note:** `ackCallback` allows the user to send data back to the
|
||||
second instance during the `app.requestSingleInstanceLock()` flow.
|
||||
This callback can be used for cases where the second instance
|
||||
needs to obtain additional information from the first instance
|
||||
before quitting.
|
||||
|
||||
Currently, the limit on the message size is kMaxMessageLength,
|
||||
or around 32kB. To be safe, keep the amount of data passed to 31kB at most.
|
||||
|
||||
In order to call the callback, `event.preventDefault()` must be called, first.
|
||||
If the callback is not called in either case, `null` will be sent back.
|
||||
If `event.preventDefault()` is not called, but `ackCallback` is called
|
||||
by the user in the event, then the behaviour is undefined.
|
||||
|
||||
This event is guaranteed to be emitted after the `ready` event of `app`
|
||||
gets emitted.
|
||||
|
||||
**Note:** Extra command line arguments might be added by Chromium,
|
||||
such as `--original-process-start-time`.
|
||||
|
||||
### Event: 'first-instance-ack'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `additionalData` unknown - A JSON object of additional data passed from the first instance, in response to the first instance's `second-instance` event.
|
||||
|
||||
This event will be emitted within the second instance during the call to `app.requestSingleInstanceLock()`, when the first instance calls the `ackCallback` provided by the `second-instance` event handler.
|
||||
|
||||
## Methods
|
||||
|
||||
The `app` object has the following methods:
|
||||
@@ -930,9 +954,9 @@ app.setJumpList([
|
||||
])
|
||||
```
|
||||
|
||||
### `app.requestSingleInstanceLock()`
|
||||
### `app.requestSingleInstanceLock([additionalData])`
|
||||
|
||||
* `additionalData` unknown (optional) - A JSON object containing additional data to send to the first instance.
|
||||
* `additionalData` Record<any, any> (optional) - A JSON object containing additional data to send to the first instance.
|
||||
|
||||
Returns `boolean`
|
||||
|
||||
@@ -959,6 +983,13 @@ starts:
|
||||
const { app } = require('electron')
|
||||
let myWindow = null
|
||||
|
||||
app.on('first-instance-ack', (event, additionalData) => {
|
||||
// Print out the ack received from the first instance.
|
||||
// Note this event handler must come before the requestSingleInstanceLock call.
|
||||
// Expected output: '{"myAckKey":"myAckValue"}'
|
||||
console.log(JSON.stringify(additionalData))
|
||||
})
|
||||
|
||||
const additionalData = { myKey: 'myValue' }
|
||||
const gotTheLock = app.requestSingleInstanceLock(additionalData)
|
||||
|
||||
@@ -966,14 +997,19 @@ if (!gotTheLock) {
|
||||
app.quit()
|
||||
} else {
|
||||
app.on('second-instance', (event, commandLine, workingDirectory, additionalData) => {
|
||||
// We must call preventDefault if we're sending back data.
|
||||
event.preventDefault()
|
||||
// Print out data received from the second instance.
|
||||
console.log(additionalData)
|
||||
// Expected output: '{"myKey":"myValue"}'
|
||||
console.log(JSON.stringify(additionalData))
|
||||
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
if (myWindow) {
|
||||
if (myWindow.isMinimized()) myWindow.restore()
|
||||
myWindow.focus()
|
||||
}
|
||||
const ackData = { myAckKey: 'myAckValue' }
|
||||
ackCallback(ackData)
|
||||
})
|
||||
|
||||
// Create myWindow, load the rest of the app, etc...
|
||||
|
||||
@@ -64,7 +64,7 @@ win.loadURL('https://github.com')
|
||||
```
|
||||
|
||||
Note that even for apps that use `ready-to-show` event, it is still recommended
|
||||
to set `backgroundColor` to make app feel more native.
|
||||
to set `backgroundColor` to make the app feel more native.
|
||||
|
||||
## Parent and child windows
|
||||
|
||||
@@ -388,9 +388,10 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
contain the layout of the document—without requiring scrolling. Enabling
|
||||
this will cause the `preferred-size-changed` event to be emitted on the
|
||||
`WebContents` when the preferred size changes. Default is `false`.
|
||||
* `titleBarOverlay` Object | boolean (optional) - When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS or using a `titleBarStyle` so that the standard window controls ("traffic lights" on macOS) are visible, this property enables the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and [CSS Environment Variables][overlay-css-env-vars]. Specifying `true` will result in an overlay with default system colors. Default is `false`.
|
||||
* `color` string (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled. Default is the system color.
|
||||
* `symbolColor` string (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled. Default is the system color.
|
||||
* `titleBarOverlay` Object | Boolean (optional) - When using a frameless window in conjunction with `win.setWindowButtonVisibility(true)` on macOS or using a `titleBarStyle` so that the standard window controls ("traffic lights" on macOS) are visible, this property enables the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and [CSS Environment Variables][overlay-css-env-vars]. Specifying `true` will result in an overlay with default system colors. Default is `false`.
|
||||
* `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled. Default is the system color.
|
||||
* `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled. Default is the system color.
|
||||
* `height` Integer (optional) _macOS_ _Windows_ - The height of the title bar and Window Controls Overlay in pixels. Default is system height.
|
||||
|
||||
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
|
||||
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
|
||||
@@ -556,7 +557,7 @@ Returns:
|
||||
|
||||
Emitted before the window is moved. On Windows, calling `event.preventDefault()` will prevent the window from being moved.
|
||||
|
||||
Note that this is only emitted when the window is being resized manually. Resizing the window with `setBounds`/`setSize` will not emit this event.
|
||||
Note that this is only emitted when the window is being moved manually. Moving the window with `setPosition`/`setBounds`/`center` will not emit this event.
|
||||
|
||||
#### Event: 'move'
|
||||
|
||||
@@ -996,7 +997,7 @@ APIs like `win.setSize`.
|
||||
is `true`). Default is `#FFF` (white).
|
||||
|
||||
Sets the background color of the window. See [Setting
|
||||
`backgroundColor`](#setting-backgroundcolor).
|
||||
`backgroundColor`](#setting-the-backgroundcolor-property).
|
||||
|
||||
#### `win.previewFile(path[, displayName])` _macOS_
|
||||
|
||||
@@ -1041,7 +1042,7 @@ Returns [`Rectangle`](structures/rectangle.md) - The `bounds` of the window as `
|
||||
#### `win.getBackgroundColor()`
|
||||
|
||||
Returns `string` - Gets the background color of the window. See [Setting
|
||||
`backgroundColor`](#setting-backgroundcolor).
|
||||
`backgroundColor`](#setting-the-backgroundcolor-property).
|
||||
|
||||
#### `win.setContentBounds(bounds[, animate])`
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ Writes `markup` to the clipboard.
|
||||
```js
|
||||
const { clipboard } = require('electron')
|
||||
|
||||
clipboard.writeHTML('<b>Hi</b')
|
||||
clipboard.writeHTML('<b>Hi</b>')
|
||||
```
|
||||
|
||||
### `clipboard.readImage([type])`
|
||||
|
||||
@@ -102,8 +102,8 @@ has been included below for completeness:
|
||||
| `boolean` | Simple | ✅ | ✅ | N/A |
|
||||
| `Object` | Complex | ✅ | ✅ | Keys must be supported using only "Simple" types in this table. Values must be supported in this table. Prototype modifications are dropped. Sending custom classes will copy values but not the prototype. |
|
||||
| `Array` | Complex | ✅ | ✅ | Same limitations as the `Object` type |
|
||||
| `Error` | Complex | ✅ | ✅ | Errors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context |
|
||||
| `Promise` | Complex | ✅ | ✅ | Promises are only proxied if they are the return value or exact parameter. Promises nested in arrays or objects will be dropped. |
|
||||
| `Error` | Complex | ✅ | ✅ | Errors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context, and any custom properties on the Error object [will be lost](https://github.com/electron/electron/issues/25596) |
|
||||
| `Promise` | Complex | ✅ | ✅ | N/A
|
||||
| `Function` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending classes or constructors will not work. |
|
||||
| [Cloneable Types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) | Simple | ✅ | ✅ | See the linked document on cloneable types |
|
||||
| `Element` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending custom elements will not work. |
|
||||
|
||||
@@ -285,7 +285,7 @@ If `browserWindow` is not shown dialog will not be attached to it. In such case
|
||||
include a checkbox with the given label.
|
||||
* `checkboxChecked` boolean (optional) - Initial checked state of the
|
||||
checkbox. `false` by default.
|
||||
* `icon` [NativeImage](native-image.md) (optional)
|
||||
* `icon` ([NativeImage](native-image.md) | string) (optional)
|
||||
* `textWidth` Integer (optional) _macOS_ - Custom width of the text in the message box.
|
||||
* `cancelId` Integer (optional) - The index of the button to be used to cancel the dialog, via
|
||||
the `Esc` key. By default this is assigned to the first button with "cancel" or "no" as the
|
||||
|
||||
@@ -28,7 +28,7 @@ When `informational` is passed, the dock icon will bounce for one second.
|
||||
However, the request remains active until either the application becomes active
|
||||
or the request is canceled.
|
||||
|
||||
**Nota Bene:** This method can only be used while the app is not focused; when the app is focused it will return -1.
|
||||
**Note:** This method can only be used while the app is not focused; when the app is focused it will return -1.
|
||||
|
||||
#### `dock.cancelBounce(id)` _macOS_
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ Prints Chromium's internal logging to the console.
|
||||
|
||||
Setting this variable is the same as passing `--enable-logging`
|
||||
on the command line. For more info, see `--enable-logging` in [command-line
|
||||
switches](./command-line-switches.md#enable-loggingfile).
|
||||
switches](./command-line-switches.md#--enable-loggingfile).
|
||||
|
||||
### `ELECTRON_LOG_FILE`
|
||||
|
||||
@@ -130,7 +130,7 @@ Sets the file destination for Chromium's internal logging.
|
||||
|
||||
Setting this variable is the same as passing `--log-file`
|
||||
on the command line. For more info, see `--log-file` in [command-line
|
||||
switches](./command-line-switches.md#log-filepath).
|
||||
switches](./command-line-switches.md#--log-filepath).
|
||||
|
||||
### `ELECTRON_DEBUG_DRAG_REGIONS`
|
||||
|
||||
|
||||
@@ -80,3 +80,25 @@ An `Integer` indicating the HTTP protocol major version number.
|
||||
An `Integer` indicating the HTTP protocol minor version number.
|
||||
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
|
||||
#### `response.rawHeaders`
|
||||
|
||||
A `string[]` containing the raw HTTP response headers exactly as they were
|
||||
received. The keys and values are in the same list. It is not a list of
|
||||
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
|
||||
// Prints something like:
|
||||
//
|
||||
// [ 'user-agent',
|
||||
// 'this is invalid because there can be only one',
|
||||
// 'User-Agent',
|
||||
// 'curl/7.22.0',
|
||||
// 'Host',
|
||||
// '127.0.0.1:8000',
|
||||
// 'ACCEPT',
|
||||
// '*/*' ]
|
||||
console.log(request.rawHeaders)
|
||||
```
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
---
|
||||
title: "ipcMain"
|
||||
description: "Communicate asynchronously from the main process to renderer processes."
|
||||
slug: ipc-main
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
# ipcMain
|
||||
|
||||
> Communicate asynchronously from the main process to renderer processes.
|
||||
@@ -9,7 +16,9 @@ process, it handles asynchronous and synchronous messages sent from a renderer
|
||||
process (web page). Messages sent from a renderer will be emitted to this
|
||||
module.
|
||||
|
||||
## Sending Messages
|
||||
For usage examples, check out the [IPC tutorial].
|
||||
|
||||
## Sending messages
|
||||
|
||||
It is also possible to send messages from the main process to the renderer
|
||||
process, see [webContents.send][web-contents-send] for more information.
|
||||
@@ -21,36 +30,6 @@ process, see [webContents.send][web-contents-send] for more information.
|
||||
coming from frames that aren't the main frame (e.g. iframes) whereas
|
||||
`event.sender.send(...)` will always send to the main frame.
|
||||
|
||||
An example of sending and handling messages between the render and main
|
||||
processes:
|
||||
|
||||
```javascript
|
||||
// In main process.
|
||||
const { ipcMain } = require('electron')
|
||||
ipcMain.on('asynchronous-message', (event, arg) => {
|
||||
console.log(arg) // prints "ping"
|
||||
event.reply('asynchronous-reply', 'pong')
|
||||
})
|
||||
|
||||
ipcMain.on('synchronous-message', (event, arg) => {
|
||||
console.log(arg) // prints "ping"
|
||||
event.returnValue = 'pong'
|
||||
})
|
||||
```
|
||||
|
||||
```javascript
|
||||
// In renderer process (web page).
|
||||
// NB. Electron APIs are only accessible from preload, unless contextIsolation is disabled.
|
||||
// See https://www.electronjs.org/docs/tutorial/process-model#preload-scripts for more details.
|
||||
const { ipcRenderer } = require('electron')
|
||||
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"
|
||||
|
||||
ipcRenderer.on('asynchronous-reply', (event, arg) => {
|
||||
console.log(arg) // prints "pong"
|
||||
})
|
||||
ipcRenderer.send('asynchronous-message', 'ping')
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
The `ipcMain` module has the following method to listen for events:
|
||||
@@ -59,7 +38,7 @@ The `ipcMain` module has the following method to listen for events:
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` IpcMainEvent
|
||||
* `event` [IpcMainEvent][ipc-main-event]
|
||||
* `...args` any[]
|
||||
|
||||
Listens to `channel`, when a new message arrives `listener` would be called with
|
||||
@@ -69,7 +48,7 @@ Listens to `channel`, when a new message arrives `listener` would be called with
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` IpcMainEvent
|
||||
* `event` [IpcMainEvent][ipc-main-event]
|
||||
* `...args` any[]
|
||||
|
||||
Adds a one time `listener` function for the event. This `listener` is invoked
|
||||
@@ -93,8 +72,8 @@ Removes listeners of the specified `channel`.
|
||||
### `ipcMain.handle(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `event` IpcMainInvokeEvent
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
|
||||
* `...args` any[]
|
||||
|
||||
Adds a handler for an `invoke`able IPC. This handler will be called whenever a
|
||||
@@ -104,14 +83,14 @@ If `listener` returns a Promise, the eventual result of the promise will be
|
||||
returned as a reply to the remote caller. Otherwise, the return value of the
|
||||
listener will be used as the value of the reply.
|
||||
|
||||
```js
|
||||
// Main process
|
||||
```js title='Main Process'
|
||||
ipcMain.handle('my-invokable-ipc', async (event, ...args) => {
|
||||
const result = await somePromise(...args)
|
||||
return result
|
||||
})
|
||||
```
|
||||
|
||||
// Renderer process
|
||||
```js title='Renderer Process'
|
||||
async () => {
|
||||
const result = await ipcRenderer.invoke('my-invokable-ipc', arg1, arg2)
|
||||
// ...
|
||||
@@ -130,7 +109,7 @@ provided to the renderer process. Please refer to
|
||||
### `ipcMain.handleOnce(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `event` IpcMainInvokeEvent
|
||||
* `...args` any[]
|
||||
|
||||
@@ -146,13 +125,16 @@ Removes any handler for `channel`, if present.
|
||||
## IpcMainEvent object
|
||||
|
||||
The documentation for the `event` object passed to the `callback` can be found
|
||||
in the [`ipc-main-event`](structures/ipc-main-event.md) structure docs.
|
||||
in the [`ipc-main-event`][ipc-main-event] structure docs.
|
||||
|
||||
## IpcMainInvokeEvent object
|
||||
|
||||
The documentation for the `event` object passed to `handle` callbacks can be
|
||||
found in the [`ipc-main-invoke-event`](structures/ipc-main-invoke-event.md)
|
||||
found in the [`ipc-main-invoke-event`][ipc-main-invoke-event]
|
||||
structure docs.
|
||||
|
||||
[IPC tutorial]: ../tutorial/ipc.md
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[web-contents-send]: web-contents.md#contentssendchannel-args
|
||||
[web-contents-send]: ../api/web-contents.md#contentssendchannel-args
|
||||
[ipc-main-event]:../api/structures/ipc-main-event.md
|
||||
[ipc-main-invoke-event]:../api/structures/ipc-main-invoke-event.md
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
---
|
||||
title: "ipcRenderer"
|
||||
description: "Communicate asynchronously from a renderer process to the main process."
|
||||
slug: ipc-renderer
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
# ipcRenderer
|
||||
|
||||
> Communicate asynchronously from a renderer process to the main process.
|
||||
@@ -9,7 +16,7 @@ methods so you can send synchronous and asynchronous messages from the render
|
||||
process (web page) to the main process. You can also receive replies from the
|
||||
main process.
|
||||
|
||||
See [ipcMain](ipc-main.md) for code examples.
|
||||
See [IPC tutorial](../tutorial/ipc.md) for code examples.
|
||||
|
||||
## Methods
|
||||
|
||||
@@ -70,7 +77,7 @@ throw an exception.
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
The main process handles it by listening for `channel` with the
|
||||
[`ipcMain`](ipc-main.md) module.
|
||||
[`ipcMain`](./ipc-main.md) module.
|
||||
|
||||
If you need to transfer a [`MessagePort`][] to the main process, use [`ipcRenderer.postMessage`](#ipcrendererpostmessagechannel-message-transfer).
|
||||
|
||||
@@ -98,7 +105,7 @@ throw an exception.
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
The main process should listen for `channel` with
|
||||
[`ipcMain.handle()`](ipc-main.md#ipcmainhandlechannel-listener).
|
||||
[`ipcMain.handle()`](./ipc-main.md#ipcmainhandlechannel-listener).
|
||||
|
||||
For example:
|
||||
|
||||
@@ -124,11 +131,11 @@ If you do not need a response to the message, consider using [`ipcRenderer.send`
|
||||
* `channel` string
|
||||
* `...args` any[]
|
||||
|
||||
Returns `any` - The value sent back by the [`ipcMain`](ipc-main.md) handler.
|
||||
Returns `any` - The value sent back by the [`ipcMain`](./ipc-main.md) handler.
|
||||
|
||||
Send a message to the main process via `channel` and expect a result
|
||||
synchronously. Arguments will be serialized with the [Structured Clone
|
||||
Algorithm][SCA], just like [`window.postMessage`][], so prototype chains will not be
|
||||
Algorithm][SCA], just like [`window.postMessage`], so prototype chains will not be
|
||||
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
@@ -140,13 +147,13 @@ throw an exception.
|
||||
> Electron's IPC to the main process, as the main process would have no way to decode
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
The main process handles it by listening for `channel` with [`ipcMain`](ipc-main.md) module,
|
||||
The main process handles it by listening for `channel` with [`ipcMain`](./ipc-main.md) module,
|
||||
and replies by setting `event.returnValue`.
|
||||
|
||||
> :warning: **WARNING**: Sending a synchronous message will block the whole
|
||||
> renderer process until the reply is received, so use this method only as a
|
||||
> last resort. It's much better to use the asynchronous version,
|
||||
> [`invoke()`](ipc-renderer.md#ipcrendererinvokechannel-args).
|
||||
> [`invoke()`](./ipc-renderer.md#ipcrendererinvokechannel-args).
|
||||
|
||||
### `ipcRenderer.postMessage(channel, message, [transfer])`
|
||||
|
||||
@@ -158,7 +165,7 @@ Send a message to the main process, optionally transferring ownership of zero
|
||||
or more [`MessagePort`][] objects.
|
||||
|
||||
The transferred `MessagePort` objects will be available in the main process as
|
||||
[`MessagePortMain`](message-port-main.md) objects by accessing the `ports`
|
||||
[`MessagePortMain`](./message-port-main.md) objects by accessing the `ports`
|
||||
property of the emitted event.
|
||||
|
||||
For example:
|
||||
@@ -197,7 +204,7 @@ the host page instead of the main process.
|
||||
## Event object
|
||||
|
||||
The documentation for the `event` object passed to the `callback` can be found
|
||||
in the [`ipc-renderer-event`](structures/ipc-renderer-event.md) structure docs.
|
||||
in the [`ipc-renderer-event`](./structures/ipc-renderer-event.md) structure docs.
|
||||
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[SCA]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
||||
|
||||
@@ -124,7 +124,7 @@ When specifying a `role` on macOS, `label` and `accelerator` are the only
|
||||
options that will affect the menu item. All other options will be ignored.
|
||||
Lowercase `role`, e.g. `toggledevtools`, is still supported.
|
||||
|
||||
**Nota Bene:** The `enabled` and `visibility` properties are not available for top-level menu items in the tray on macOS.
|
||||
**Note:** The `enabled` and `visibility` properties are not available for top-level menu items in the tray on macOS.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
* `messageDetails` Object - Information about the console message
|
||||
* `message` string - The actual console message
|
||||
* `versionId` number - The version ID of the service worker that sent the log message
|
||||
* `source` string - The type of source for this message. Can be `javascript`, `xml`, `network`, `console-api`, `storage`, `app-cache`, `rendering`, `security`, `deprecation`, `worker`, `violation`, `intervention`, `recommendation` or `other`.
|
||||
* `source` string - The type of source for this message. Can be `javascript`, `xml`, `network`, `console-api`, `storage`, `rendering`, `security`, `deprecation`, `worker`, `violation`, `intervention`, `recommendation` or `other`.
|
||||
* `level` number - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
|
||||
* `sourceUrl` string - The URL the message came from
|
||||
* `lineNumber` number - The line number of the source that triggered this console message
|
||||
|
||||
@@ -903,8 +903,10 @@ setting with the current OS locale. This setting is persisted across restarts.
|
||||
By default Electron will download hunspell dictionaries from the Chromium CDN. If you want to override this
|
||||
behavior you can use this API to point the dictionary downloader at your own hosted version of the hunspell
|
||||
dictionaries. We publish a `hunspell_dictionaries.zip` file with each release which contains the files you need
|
||||
to host here, the file server must be **case insensitive** you must upload each file twice, once with the case it
|
||||
has in the ZIP file and once with the filename as all lower case.
|
||||
to host here.
|
||||
|
||||
The file server must be **case insensitive**. If you cannot do this, you must upload each file twice: once with
|
||||
the case it has in the ZIP file and once with the filename as all lowercase.
|
||||
|
||||
If the files present in `hunspell_dictionaries.zip` are available at `https://example.com/dictionaries/language-code.bdic`
|
||||
then you should call this api with `ses.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')`. Please
|
||||
|
||||
7
docs/api/structures/payment-discount.md
Normal file
7
docs/api/structures/payment-discount.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# PaymentDiscount Object
|
||||
|
||||
* `identifier` string - A string used to uniquely identify a discount offer for a product.
|
||||
* `keyIdentifier` string - A string that identifies the key used to generate the signature.
|
||||
* `nonce` string - A universally unique ID (UUID) value that you define.
|
||||
* `signature` string - A UTF-8 string representing the properties of a specific discount offer, cryptographically signed.
|
||||
* `timestamp` number - The date and time of the signature's creation in milliseconds, formatted in Unix epoch time.
|
||||
9
docs/api/structures/product-discount.md
Normal file
9
docs/api/structures/product-discount.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# ProductDiscount Object
|
||||
|
||||
* `identifier` string - A string used to uniquely identify a discount offer for a product.
|
||||
* `type` number - The type of discount offer.
|
||||
* `price` number - The discount price of the product in the local currency.
|
||||
* `priceLocale` string - The locale used to format the discount price of the product.
|
||||
* `paymentMode` string - The payment mode for this product discount. Can be `payAsYouGo`, `payUpFront`, or `freeTrial`.
|
||||
* `numberOfPeriods` number - An integer that indicates the number of periods the product discount is available.
|
||||
* `subscriptionPeriod` [ProductSubscriptionPeriod](product-subscription-period.md) (optional) - An object that defines the period for the product discount.
|
||||
4
docs/api/structures/product-subscription-period.md
Normal file
4
docs/api/structures/product-subscription-period.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# ProductSubscriptionPeriod Object
|
||||
|
||||
* `numberOfUnits` number - The number of units per subscription period.
|
||||
* `unit` string - The increment of time that a subscription period is specified in. Can be `day`, `week`, `month`, `year`.
|
||||
@@ -8,4 +8,11 @@
|
||||
* `price` number - The cost of the product in the local currency.
|
||||
* `formattedPrice` string - The locale formatted price of the product.
|
||||
* `currencyCode` string - 3 character code presenting a product's currency based on the ISO 4217 standard.
|
||||
* `introductoryPrice` [ProductDiscount](product-discount.md) (optional) - The object containing introductory price information for the product.
|
||||
available for the product.
|
||||
* `discounts` [ProductDiscount](product-discount.md)[] - An array of discount offers
|
||||
* `subscriptionGroupIdentifier` string - The identifier of the subscription group to which the subscription belongs.
|
||||
* `subscriptionPeriod` [ProductSubscriptionPeriod](product-subscription-period.md) (optional) - The period details for products that are subscriptions.
|
||||
* `isDownloadable` boolean - A boolean value that indicates whether the App Store has downloadable content for this product. `true` if at least one file has been associated with the product.
|
||||
* `downloadContentVersion` string - A string that identifies the version of the content.
|
||||
* `downloadContentLengths` number[] - The total size of the content, in bytes.
|
||||
|
||||
@@ -9,3 +9,5 @@
|
||||
* `payment` Object
|
||||
* `productIdentifier` string - The identifier of the purchased product.
|
||||
* `quantity` Integer - The quantity purchased.
|
||||
* `applicationUsername` string - An opaque identifier for the user’s account on your system.
|
||||
* `paymentDiscount` [PaymentDiscount](payment-discount.md) (optional) - The details of the discount offer to apply to the payment.
|
||||
|
||||
@@ -2,4 +2,3 @@
|
||||
|
||||
* `code` string
|
||||
* `url` string (optional)
|
||||
* `startLine` Integer (optional) - Default is 1.
|
||||
|
||||
@@ -35,7 +35,7 @@ for all windows, webviews, opened devtools, and devtools extension background pa
|
||||
|
||||
### `webContents.getFocusedWebContents()`
|
||||
|
||||
Returns `WebContents` - The web contents that is focused in this application, otherwise
|
||||
Returns `WebContents` | null - The web contents that is focused in this application, otherwise
|
||||
returns `null`.
|
||||
|
||||
### `webContents.fromId(id)`
|
||||
@@ -290,7 +290,7 @@ Returns:
|
||||
* `frameProcessId` Integer
|
||||
* `frameRoutingId` Integer
|
||||
|
||||
Emitted as a server side redirect occurs during navigation. For example a 302
|
||||
Emitted when a server side redirect occurs during navigation. For example a 302
|
||||
redirect.
|
||||
|
||||
This event will be emitted after `did-start-navigation` and always before the
|
||||
@@ -508,6 +508,23 @@ Returns:
|
||||
|
||||
Emitted when the user is requesting to change the zoom level using the mouse wheel.
|
||||
|
||||
#### Event: 'blur'
|
||||
|
||||
Emitted when the `WebContents` loses focus.
|
||||
|
||||
#### Event: 'focus'
|
||||
|
||||
Emitted when the `WebContents` gains focus.
|
||||
|
||||
Note that on macOS, having focus means the `WebContents` is the first responder
|
||||
of window, so switching focus between windows would not trigger the `focus` and
|
||||
`blur` events of `WebContents`, as the first responder of each window is not
|
||||
changed.
|
||||
|
||||
The `focus` and `blur` events of `WebContents` should only be used to detect
|
||||
focus change between different `WebContents` and `BrowserView` in the same
|
||||
window.
|
||||
|
||||
#### Event: 'devtools-opened'
|
||||
|
||||
Emitted when DevTools is opened.
|
||||
@@ -1084,7 +1101,7 @@ Returns `string` - The user agent for this web page.
|
||||
|
||||
* `css` string
|
||||
* `options` Object (optional)
|
||||
* `cssOrigin` string (optional) - Can be either 'user' or 'author'; Specifying 'user' enables you to prevent websites from overriding the CSS you insert. Default is 'author'.
|
||||
* `cssOrigin` string (optional) - Can be either 'user' or 'author'. Sets the [cascade origin](https://www.w3.org/TR/css3-cascade/#cascade-origin) of the inserted stylesheet. Default is 'author'.
|
||||
|
||||
Returns `Promise<string>` - A promise that resolves with a key for the inserted CSS that can later be used to remove the CSS via `contents.removeInsertedCSS(key)`.
|
||||
|
||||
@@ -1611,7 +1628,7 @@ app.whenReady().then(() => {
|
||||
|
||||
* `options` Object (optional)
|
||||
* `mode` string - Opens the devtools with specified dock state, can be
|
||||
`right`, `bottom`, `undocked`, `detach`. Defaults to last used dock state.
|
||||
`left`, `right`, `bottom`, `undocked`, `detach`. Defaults to last used dock state.
|
||||
In `undocked` mode it's possible to dock back. In `detach` mode it's not.
|
||||
* `activate` boolean (optional) - Whether to bring the opened devtools window
|
||||
to the foreground. The default is `true`.
|
||||
@@ -1839,7 +1856,7 @@ the cursor when dragging.
|
||||
|
||||
#### `contents.savePage(fullPath, saveType)`
|
||||
|
||||
* `fullPath` string - The full file path.
|
||||
* `fullPath` string - The absolute file path.
|
||||
* `saveType` string - Specify the save type.
|
||||
* `HTMLOnly` - Save only the HTML of the page.
|
||||
* `HTMLComplete` - Save complete-html page.
|
||||
|
||||
@@ -98,6 +98,7 @@ Some examples of valid `urls`:
|
||||
* `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` string
|
||||
* `timestamp` Double
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md) (optional)
|
||||
* `requestHeaders` Record<string, string>
|
||||
* `callback` Function
|
||||
* `beforeSendResponse` Object
|
||||
|
||||
@@ -73,6 +73,11 @@ creating the window. Note that this is more powerful than passing options
|
||||
through the feature string, as the renderer has more limited privileges in
|
||||
deciding security preferences than the main process.
|
||||
|
||||
In addition to passing in `action` and `overrideBrowserWindowOptions`,
|
||||
`outlivesOpener` can be passed like: `{ action: 'allow', outlivesOpener: true,
|
||||
overrideBrowserWindowOptions: { ... } }`. If set to `true`, the newly created
|
||||
window will not close when the opener window closes. The default value is `false`.
|
||||
|
||||
### Native `Window` example
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -12,6 +12,25 @@ 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 (20.0)
|
||||
|
||||
### Default Changed: renderers without `nodeIntegration: true` are sandboxed by default
|
||||
|
||||
Previously, renderers that specified a preload script defaulted to being
|
||||
unsandboxed. This meant that by default, preload scripts had access to Node.js.
|
||||
In Electron 20, this default has changed. Beginning in Electron 20, renderers
|
||||
will be sandboxed by default, unless `nodeIntegration: true` or `sandbox: false`
|
||||
is specified.
|
||||
|
||||
If your preload scripts do not depend on Node, no action is needed. If your
|
||||
preload scripts _do_ depend on Node, either refactor them to remove Node usage
|
||||
from the renderer, or explicitly specify `sandbox: false` for the relevant
|
||||
renderers.
|
||||
|
||||
## Planned Breaking API Changes (19.0)
|
||||
|
||||
*None (yet)*
|
||||
|
||||
## Planned Breaking API Changes (18.0)
|
||||
|
||||
### Removed: `nativeWindowOpen`
|
||||
|
||||
@@ -98,45 +98,40 @@ $ gclient sync -f
|
||||
|
||||
## Building
|
||||
|
||||
**Set the environment variable for chromium build tools**
|
||||
|
||||
On Linux & MacOS
|
||||
|
||||
```sh
|
||||
$ cd src
|
||||
$ export CHROMIUM_BUILDTOOLS_PATH=`pwd`/buildtools
|
||||
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\") $GN_EXTRA_ARGS"
|
||||
```
|
||||
|
||||
Or on Windows (without the optional argument):
|
||||
On Windows:
|
||||
|
||||
```sh
|
||||
$ cd src
|
||||
$ set CHROMIUM_BUILDTOOLS_PATH=%cd%\buildtools
|
||||
```
|
||||
|
||||
**To generate Testing build config of Electron:**
|
||||
|
||||
```sh
|
||||
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\")"
|
||||
```
|
||||
|
||||
This will generate a build directory `out/Testing` under `src/` with
|
||||
the testing build configuration. You can replace `Testing` with another name,
|
||||
but it should be a subdirectory of `out`.
|
||||
Also you shouldn't have to run `gn gen` again—if you want to change the
|
||||
build arguments, you can run `gn args out/Testing` to bring up an editor.
|
||||
|
||||
To see the list of available build configuration options, run `gn args
|
||||
out/Testing --list`.
|
||||
|
||||
**For generating Testing build config of
|
||||
Electron:**
|
||||
**To generate Release build config of Electron:**
|
||||
|
||||
```sh
|
||||
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\") $GN_EXTRA_ARGS"
|
||||
$ gn gen out/Release --args="import(\"//electron/build/args/release.gn\")"
|
||||
```
|
||||
|
||||
**For generating Release (aka "non-component" or "static") build config of
|
||||
Electron:**
|
||||
**Note:** This will generate a `out/Testing` or `out/Release` build directory under `src/` with the testing or release build depending upon the configuration passed above. You can replace `Testing|Release` with another names, but it should be a subdirectory of `out`.
|
||||
|
||||
```sh
|
||||
$ gn gen out/Release --args="import(\"//electron/build/args/release.gn\") $GN_EXTRA_ARGS"
|
||||
```
|
||||
Also you shouldn't have to run `gn gen` again—if you want to change the build arguments, you can run `gn args out/Testing` to bring up an editor. To see the list of available build configuration options, run `gn args out/Testing --list`.
|
||||
|
||||
**To build, run `ninja` with the `electron` target:**
|
||||
Nota Bene: This will also take a while and probably heat up your lap.
|
||||
Note: This will also take a while and probably heat up your lap.
|
||||
|
||||
For the testing configuration:
|
||||
|
||||
@@ -169,13 +164,13 @@ $ ./out/Testing/electron
|
||||
On linux, first strip the debugging and symbol information:
|
||||
|
||||
```sh
|
||||
electron/script/strip-binaries.py -d out/Release
|
||||
$ electron/script/strip-binaries.py -d out/Release
|
||||
```
|
||||
|
||||
To package the electron build as a distributable zip file:
|
||||
|
||||
```sh
|
||||
ninja -C out/Release electron:electron_dist_zip
|
||||
$ ninja -C out/Release electron:electron_dist_zip
|
||||
```
|
||||
|
||||
### Cross-compiling
|
||||
|
||||
@@ -29,7 +29,17 @@ Follow the guidelines below for building **Electron itself** on Linux, for the p
|
||||
* [clang](https://clang.llvm.org/get_started.html) 3.4 or later.
|
||||
* Development headers of GTK 3 and libnotify.
|
||||
|
||||
On Ubuntu, install the following libraries:
|
||||
On Ubuntu >= 20.04, install the following libraries:
|
||||
|
||||
```sh
|
||||
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk-3-dev \
|
||||
libnotify-dev libasound2-dev libcap-dev \
|
||||
libcups2-dev libxtst-dev \
|
||||
libxss1 libnss3-dev gcc-multilib g++-multilib curl \
|
||||
gperf bison python3-dbusmock openjdk-8-jre
|
||||
```
|
||||
|
||||
On Ubuntu < 20.04, install the following libraries:
|
||||
|
||||
```sh
|
||||
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk-3-dev \
|
||||
|
||||
@@ -43,8 +43,9 @@ SRV*c:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*c:\code\sym
|
||||
|
||||
## Using the symbol server in Visual Studio
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
## Troubleshooting: Symbols will not load
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ contribute:
|
||||
|
||||
## Asking for General Help
|
||||
|
||||
["Finding Support"](../tutorial/support.md#finding-support) has a
|
||||
[The Electron website](https://electronjs.org/community) has a
|
||||
list of resources for getting programming help, reporting security issues,
|
||||
contributing, and more. Please use the issue tracker for bugs only!
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ $ git push origin my-branch
|
||||
### Step 9: Opening the Pull Request
|
||||
|
||||
From within GitHub, opening a new pull request will present you with a template
|
||||
that should be filled out. It can be found [here](../../.github/PULL_REQUEST_TEMPLATE.md).
|
||||
that should be filled out. It can be found [here](https://github.com/electron/electron/blob/main/.github/PULL_REQUEST_TEMPLATE.md).
|
||||
|
||||
If you do not adequately complete this template, your PR may be delayed in being merged as maintainers
|
||||
seek more information or clarify ambiguities.
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<h1>Asynchronous messages</h1>
|
||||
<i>Supports: Win, macOS, Linux <span>|</span> Process: Both</i>
|
||||
<div>
|
||||
<div>
|
||||
<button id="async-msg">Ping</button>
|
||||
<span id="async-reply"></span>
|
||||
</div>
|
||||
<p>Using <code>ipc</code> to send messages between processes asynchronously is the preferred method since it will return when finished without blocking other operations in the same process.</p>
|
||||
|
||||
<p>This example sends a "ping" from this process (renderer) to the main process. The main process then replies with "pong".</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// You can also require other files to run in this process
|
||||
require('./renderer.js')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,29 +0,0 @@
|
||||
const { app, BrowserWindow, ipcMain } = require('electron')
|
||||
|
||||
let mainWindow = null
|
||||
|
||||
function createWindow () {
|
||||
const windowOptions = {
|
||||
width: 600,
|
||||
height: 400,
|
||||
title: 'Asynchronous messages',
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
}
|
||||
|
||||
mainWindow = new BrowserWindow(windowOptions)
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
ipcMain.on('asynchronous-message', (event, arg) => {
|
||||
event.sender.send('asynchronous-reply', 'pong')
|
||||
})
|
||||
@@ -1,12 +0,0 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
const asyncMsgBtn = document.getElementById('async-msg')
|
||||
|
||||
asyncMsgBtn.addEventListener('click', () => {
|
||||
ipcRenderer.send('asynchronous-message', 'ping')
|
||||
})
|
||||
|
||||
ipcRenderer.on('asynchronous-reply', (event, arg) => {
|
||||
const message = `Asynchronous message reply: ${arg}`
|
||||
document.getElementById('async-reply').innerHTML = message
|
||||
})
|
||||
@@ -1,27 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<h1>Synchronous messages</h1>
|
||||
<i>Supports: Win, macOS, Linux <span>|</span> Process: Both</i>
|
||||
<div>
|
||||
<div>
|
||||
<button id="sync-msg">Ping</button>
|
||||
<span id="sync-reply"></span>
|
||||
</div>
|
||||
<p>You can use the <code>ipc</code> module to send synchronous messages between processes as well, but note that the synchronous nature of this method means that it <b>will block</b> other operations while completing its task.</p>
|
||||
|
||||
<p>This example sends a synchronous message, "ping", from this process (renderer) to the main process. The main process then replies with "pong".</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// You can also require other files to run in this process
|
||||
require('./renderer.js')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,29 +0,0 @@
|
||||
const { app, BrowserWindow, ipcMain } = require('electron')
|
||||
|
||||
let mainWindow = null
|
||||
|
||||
function createWindow () {
|
||||
const windowOptions = {
|
||||
width: 600,
|
||||
height: 400,
|
||||
title: 'Synchronous Messages',
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
}
|
||||
|
||||
mainWindow = new BrowserWindow(windowOptions)
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
ipcMain.on('synchronous-message', (event, arg) => {
|
||||
event.returnValue = 'pong'
|
||||
})
|
||||
@@ -1,9 +0,0 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
const syncMsgBtn = document.getElementById('sync-msg')
|
||||
|
||||
syncMsgBtn.addEventListener('click', () => {
|
||||
const reply = ipcRenderer.sendSync('synchronous-message', 'ping')
|
||||
const message = `Synchronous message reply: ${reply}`
|
||||
document.getElementById('sync-reply').innerHTML = message
|
||||
})
|
||||
14
docs/fiddles/ipc/pattern-1/index.html
Normal file
14
docs/fiddles/ipc/pattern-1/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
<body>
|
||||
Title: <input id="title"/>
|
||||
<button id="btn" type="button">Set</button>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
30
docs/fiddles/ipc/pattern-1/main.js
Normal file
30
docs/fiddles/ipc/pattern-1/main.js
Normal file
@@ -0,0 +1,30 @@
|
||||
const {app, BrowserWindow, ipcMain} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('set-title', (event, title) => {
|
||||
const webContents = event.sender
|
||||
const win = BrowserWindow.fromWebContents(webContents)
|
||||
win.setTitle(title)
|
||||
})
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
5
docs/fiddles/ipc/pattern-1/preload.js
Normal file
5
docs/fiddles/ipc/pattern-1/preload.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
setTitle: (title) => ipcRenderer.send('set-title', title)
|
||||
})
|
||||
6
docs/fiddles/ipc/pattern-1/renderer.js
Normal file
6
docs/fiddles/ipc/pattern-1/renderer.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const setButton = document.getElementById('btn')
|
||||
const titleInput = document.getElementById('title')
|
||||
setButton.addEventListener('click', () => {
|
||||
const title = titleInput.value
|
||||
window.electronAPI.setTitle(title)
|
||||
});
|
||||
14
docs/fiddles/ipc/pattern-2/index.html
Normal file
14
docs/fiddles/ipc/pattern-2/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Dialog</title>
|
||||
</head>
|
||||
<body>
|
||||
<button type="button" id="btn">Open a File</button>
|
||||
File path: <strong id="filePath"></strong>
|
||||
<script src='./renderer.js'></script>
|
||||
</body>
|
||||
</html>
|
||||
32
docs/fiddles/ipc/pattern-2/main.js
Normal file
32
docs/fiddles/ipc/pattern-2/main.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const {app, BrowserWindow, ipcMain, dialog} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
async function handleFileOpen() {
|
||||
const { canceled, filePaths } = await dialog.showOpenDialog()
|
||||
if (canceled) {
|
||||
return
|
||||
} else {
|
||||
return filePaths[0]
|
||||
}
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
ipcMain.handle('dialog:openFile', handleFileOpen)
|
||||
createWindow()
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
5
docs/fiddles/ipc/pattern-2/preload.js
Normal file
5
docs/fiddles/ipc/pattern-2/preload.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI',{
|
||||
openFile: () => ipcRenderer.invoke('dialog:openFile')
|
||||
})
|
||||
7
docs/fiddles/ipc/pattern-2/renderer.js
Normal file
7
docs/fiddles/ipc/pattern-2/renderer.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const btn = document.getElementById('btn')
|
||||
const filePathElement = document.getElementById('filePath')
|
||||
|
||||
btn.addEventListener('click', async () => {
|
||||
const filePath = await window.electronAPI.openFile()
|
||||
filePathElement.innerText = filePath
|
||||
})
|
||||
13
docs/fiddles/ipc/pattern-3/index.html
Normal file
13
docs/fiddles/ipc/pattern-3/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Menu Counter</title>
|
||||
</head>
|
||||
<body>
|
||||
Current value: <strong id="counter">0</strong>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
48
docs/fiddles/ipc/pattern-3/main.js
Normal file
48
docs/fiddles/ipc/pattern-3/main.js
Normal file
@@ -0,0 +1,48 @@
|
||||
const {app, BrowserWindow, Menu, ipcMain} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
const menu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: app.name,
|
||||
submenu: [
|
||||
{
|
||||
click: () => mainWindow.webContents.send('update-counter', 1),
|
||||
label: 'Increment',
|
||||
},
|
||||
{
|
||||
click: () => mainWindow.webContents.send('update-counter', -1),
|
||||
label: 'Decrement',
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
])
|
||||
|
||||
Menu.setApplicationMenu(menu)
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
mainWindow.webContents.openDevTools()
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
ipcMain.on('counter-value', (_event, value) => {
|
||||
console.log(value) // will print value to Node console
|
||||
})
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
5
docs/fiddles/ipc/pattern-3/preload.js
Normal file
5
docs/fiddles/ipc/pattern-3/preload.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
handleCounter: (callback) => ipcRenderer.on('update-counter', callback)
|
||||
})
|
||||
8
docs/fiddles/ipc/pattern-3/renderer.js
Normal file
8
docs/fiddles/ipc/pattern-3/renderer.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const counter = document.getElementById('counter')
|
||||
|
||||
window.electronAPI.handleCounter((event, value) => {
|
||||
const oldValue = Number(counter.innerText)
|
||||
const newValue = oldValue + value
|
||||
counter.innerText = newValue
|
||||
event.reply('counter-value', newValue)
|
||||
})
|
||||
BIN
docs/images/vs-options-debugging-symbols.png
Normal file
BIN
docs/images/vs-options-debugging-symbols.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
docs/images/vs-tools-options.png
Normal file
BIN
docs/images/vs-tools-options.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -1,29 +1,100 @@
|
||||
# Electron Release Timelines
|
||||
# Electron Releases
|
||||
|
||||
Special notes:
|
||||
Electron frequently releases major versions alongside every other Chromium release.
|
||||
This document focuses on the release cadence and version support policy.
|
||||
For a more in-depth guide on our git branches and how Electron uses semantic versions,
|
||||
check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
|
||||
## Timeline
|
||||
|
||||
| Electron | Alpha | Beta | Stable | Chrome | Node | Supported |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- | ---- |
|
||||
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | M61 | v8.9 | 🚫 |
|
||||
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | M66 | v10.2 | 🚫 |
|
||||
| 4.0.0 | -- | 2018-Oct-11 | 2018-Dec-20 | M69 | v10.11 | 🚫 |
|
||||
| 5.0.0 | -- | 2019-Jan-22 | 2019-Apr-24 | M73 | v12.0 | 🚫 |
|
||||
| 6.0.0 | -- | 2019-May-01 | 2019-Jul-30 | M76 | v12.4 | 🚫 |
|
||||
| 7.0.0 | -- | 2019-Aug-01 | 2019-Oct-22 | M78 | v12.8 | 🚫 |
|
||||
| 8.0.0 | -- | 2019-Oct-24 | 2020-Feb-04 | M80 | v12.13 | 🚫 |
|
||||
| 9.0.0 | -- | 2020-Feb-06 | 2020-May-19 | M83 | v12.14 | 🚫 |
|
||||
| 10.0.0 | -- | 2020-May-21 | 2020-Aug-25 | M85 | v12.16 | 🚫 |
|
||||
| 11.0.0 | -- | 2020-Aug-27 | 2020-Nov-17 | M87 | v12.18 | 🚫 |
|
||||
| 12.0.0 | -- | 2020-Nov-19 | 2021-Mar-02 | M89 | v14.16 | 🚫 |
|
||||
| 13.0.0 | -- | 2021-Mar-04 | 2021-May-25 | M91 | v14.16 | 🚫 |
|
||||
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | M93 | v14.17 | 🚫 |
|
||||
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | M94 | v16.5 | 🚫 |
|
||||
| 16.0.0 | 2021-Sep-23 | 2021-Oct-20 | 2021-Nov-16 | M96 | v16.9 | ✅ |
|
||||
| 17.0.0 | 2021-Nov-18 | 2022-Jan-06 | 2022-Feb-01 | M98 | v16.13 | ✅ |
|
||||
| 18.0.0 | 2022-Feb-03 | 2022-Mar-03 | 2022-Mar-29 | M100 | TBD | ✅ |
|
||||
| 19.0.0 | 2022-Mar-31 | 2022-Apr-30 | 2022-May-24 | M102 | TBD | ✅ |
|
||||
|
||||
**Notes:**
|
||||
|
||||
* The `-beta.1` and `stable` dates are our solid release dates.
|
||||
* We strive for weekly beta releases, however we often release more betas than scheduled.
|
||||
* We strive for weekly beta releases, but we often release more betas than scheduled.
|
||||
* All dates are our goals but there may be reasons for adjusting the stable deadline, such as security bugs.
|
||||
* Take a look at the [5.0.0 Timeline blog post](https://electronjs.org/blog/electron-5-0-timeline) for info about publicizing our release dates.
|
||||
* Since Electron 6.0, we've been targeting every other Chromium version and releasing our stable on the same day as Chrome stable. You can reference Chromium's release schedule [here](https://chromiumdash.appspot.com/schedule). See [Electron's new release cadence blog post](https://www.electronjs.org/blog/12-week-cadence) for more details on our release schedule.
|
||||
* Starting in Electron 16.0, we will release on an 8-week cadence. See [Electron's new 8-week cadence blog post](https://www.electronjs.org/blog/8-week-cadence) for more details.
|
||||
|
||||
| Electron | Alpha | Beta | Stable | Chrome | Node |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- |
|
||||
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | M61 | v8.9 |
|
||||
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | M66 | v10.2 |
|
||||
| 4.0.0 | -- | 2018-Oct-11 | 2018-Dec-20 | M69 | v10.11 |
|
||||
| 5.0.0 | -- | 2019-Jan-22 | 2019-Apr-24 | M73 | v12.0 |
|
||||
| 6.0.0 | -- | 2019-May-01 | 2019-Jul-30 | M76 | v12.4 |
|
||||
| 7.0.0 | -- | 2019-Aug-01 | 2019-Oct-22 | M78 | v12.8 |
|
||||
| 8.0.0 | -- | 2019-Oct-24 | 2020-Feb-04 | M80 | v12.13 |
|
||||
| 9.0.0 | -- | 2020-Feb-06 | 2020-May-19 | M83 | v12.14 |
|
||||
| 10.0.0 | -- | 2020-May-21 | 2020-Aug-25 | M85 | v12.16 |
|
||||
| 11.0.0 | -- | 2020-Aug-27 | 2020-Nov-17 | M87 | v12.18 |
|
||||
| 12.0.0 | -- | 2020-Nov-19 | 2021-Mar-02 | M89 | v14.16 |
|
||||
| 13.0.0 | -- | 2021-Mar-04 | 2021-May-25 | M91 | v14.16 |
|
||||
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | M93 | v14.17 |
|
||||
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | M94 | v16.5 |
|
||||
| 16.0.0 | 2021-Sep-23 | 2021-Oct-20 | 2021-Nov-16 | M96 | v16.9 |
|
||||
| 17.0.0 | 2021-Nov-18 | 2022-Jan-06 | 2022-Feb-01 | M98 | TBD |
|
||||
**Historical changes:**
|
||||
|
||||
* Since Electron 5, Electron has been publicizing its release dates ([see blog post](https://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)). When this was announced
|
||||
* 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).
|
||||
|
||||
:::info Chrome release dates
|
||||
|
||||
Chromium has the own public release schedule [here](https://chromiumdash.appspot.com/schedule).
|
||||
|
||||
:::
|
||||
|
||||
## Version support policy
|
||||
|
||||
:::info
|
||||
|
||||
Beginning in September 2021 (Electron 15), the Electron team
|
||||
will temporarily support the latest **four** stable major versions. This
|
||||
extended support is intended to help Electron developers transition to
|
||||
the [new 8-week release cadence](https://electronjs.org/blog/8-week-cadence),
|
||||
and will continue until the release of Electron 19. At that time,
|
||||
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
|
||||
for each stable release series. This means that in the case of a security fix,
|
||||
6.1.x will receive the fix, but we will not release a new version of 6.0.x.
|
||||
|
||||
The latest stable release unilaterally receives all fixes from `main`,
|
||||
and the version prior to that receives the vast majority of those fixes
|
||||
as time and bandwidth warrants. The oldest supported release line will receive
|
||||
only security fixes directly.
|
||||
|
||||
### Breaking API changes
|
||||
|
||||
When an API is changed or removed in a way that breaks existing functionality, the
|
||||
previous functionality will be supported for a minimum of two major versions when
|
||||
possible before being removed. For example, if a function takes three arguments,
|
||||
and that number is reduced to two in major version 10, the three-argument version would
|
||||
continue to work until, at minimum, major version 12. Past the minimum two-version
|
||||
threshold, we will attempt to support backwards compatibility beyond two versions
|
||||
until the maintainers feel the maintenance burden is too high to continue doing so.
|
||||
|
||||
### End-of-life
|
||||
|
||||
When a release branch reaches the end of its support cycle, the series
|
||||
will be deprecated in NPM and a final end-of-support release will be
|
||||
made. This release will add a warning to inform that an unsupported
|
||||
version of Electron is in use.
|
||||
|
||||
These steps are to help app developers learn when a branch they're
|
||||
using becomes unsupported, but without being excessively intrusive
|
||||
to end users.
|
||||
|
||||
If an application has exceptional circumstances and needs to stay
|
||||
on an unsupported series of Electron, developers can silence the
|
||||
end-of-support warning by omitting the final release from the app's
|
||||
`package.json` `devDependencies`. For example, since the 1-6-x series
|
||||
ended with an end-of-support 1.6.18 release, developers could choose
|
||||
to stay in the 1-6-x series without warnings with `devDependency` of
|
||||
`"electron": 1.6.0 - 1.6.17`.
|
||||
|
||||
@@ -48,7 +48,7 @@ Stabilization branches are branches that run parallel to `main`, taking in only
|
||||
|
||||
Since Electron 8, stabilization branches are always **major** version lines, and named against the following template `$MAJOR-x-y` e.g. `8-x-y`. Prior to that we used **minor** version lines and named them as `$MAJOR-$MINOR-x` e.g. `2-0-x`.
|
||||
|
||||
We allow for multiple stabilization branches to exist simultaneously, one for each supported version. For more details on which versions are supported, see our [Electron Release Timelines](./electron-timelines.md) doc.
|
||||
We allow for multiple stabilization branches to exist simultaneously, one for each supported version. For more details on which versions are supported, see our [Electron Releases](./electron-timelines.md) doc.
|
||||
|
||||

|
||||
|
||||
@@ -107,6 +107,15 @@ A few examples of how various SemVer ranges will pick up new releases:
|
||||
|
||||

|
||||
|
||||
### Backport request process
|
||||
|
||||
All supported release lines will accept external pull requests to backport
|
||||
fixes previously merged to `main`, though this may be on a case-by-case
|
||||
basis for some older supported lines. All contested decisions around release
|
||||
line backports will be resolved by the
|
||||
[Releases Working Group](https://github.com/electron/governance/tree/main/wg-releases)
|
||||
as an agenda item at their weekly meeting the week the backport PR is raised.
|
||||
|
||||
## Feature flags
|
||||
|
||||
Feature flags are a common practice in Chromium, and are well-established in the web-development ecosystem. In the context of Electron, a feature flag or **soft branch** must have the following properties:
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
# In-App Purchases (macOS)
|
||||
---
|
||||
title: In-App Purchases
|
||||
description: Add in-app purchases to your Mac App Store (MAS) application
|
||||
slug: in-app-purchases
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# In-App Purchases
|
||||
|
||||
## Preparing
|
||||
|
||||
|
||||
571
docs/tutorial/ipc.md
Normal file
571
docs/tutorial/ipc.md
Normal file
@@ -0,0 +1,571 @@
|
||||
---
|
||||
title: Inter-Process Communication
|
||||
description: Use the ipcMain and ipcRenderer modules to communicate between Electron processes
|
||||
slug: ipc
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
# Inter-Process Communication
|
||||
|
||||
Inter-process communication (IPC) is a key part of building feature-rich desktop applications
|
||||
in Electron. Because the main and renderer processes have different responsibilities in
|
||||
Electron's process model, IPC is the only way to perform many common tasks, such as calling a
|
||||
native API from your UI or triggering changes in your web contents from native menus.
|
||||
|
||||
## IPC channels
|
||||
|
||||
In Electron, processes communicate by passing messages through developer-defined "channels"
|
||||
with the [`ipcMain`] and [`ipcRenderer`] modules. These channels are
|
||||
**arbitrary** (you can name them anything you want) and **bidirectional** (you can use the
|
||||
same channel name for both modules).
|
||||
|
||||
In this guide, we'll be going over some fundamental IPC patterns with concrete examples that
|
||||
you can use as a reference for your app code.
|
||||
|
||||
## Understanding context-isolated processes
|
||||
|
||||
Before proceeding to implementation details, you should be familiar with the idea of using a
|
||||
[preload script] to import Node.js and Electron modules in a context-isolated renderer process.
|
||||
|
||||
* For a full overview of Electron's process model, you can read the [process model docs].
|
||||
* For a primer into exposing APIs from your preload script using the `contextBridge` module, check
|
||||
out the [context isolation tutorial].
|
||||
|
||||
## Pattern 1: Renderer to main (one-way)
|
||||
|
||||
To fire a one-way IPC message from a renderer process to the main process, you can use the
|
||||
[`ipcRenderer.send`] API to send a message that is then received by the [`ipcMain.on`] API.
|
||||
|
||||
You usually use this pattern to call a main process API from your web contents. We'll demonstrate
|
||||
this pattern by creating a simple app that can programmatically change its window title.
|
||||
|
||||
For this demo, you'll need to add code to your main process, your renderer process, and a preload
|
||||
script. The full code is below, but we'll be explaining each file individually in the following
|
||||
sections.
|
||||
|
||||
```fiddle docs/fiddles/ipc/pattern-1
|
||||
```
|
||||
|
||||
### 1. Listen for events with `ipcMain.on`
|
||||
|
||||
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)'
|
||||
const {app, BrowserWindow, ipcMain} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
//...
|
||||
|
||||
function handleSetTitle (event, title) {
|
||||
const webContents = event.sender
|
||||
const win = BrowserWindow.fromWebContents(webContents)
|
||||
win.setTitle(title)
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
ipcMain.on('set-title', handleSetTitle)
|
||||
createWindow()
|
||||
}
|
||||
//...
|
||||
```
|
||||
|
||||
The above `handleSetTitle` callback has two parameters: an [IpcMainEvent] structure and a
|
||||
`title` string. Whenever a message comes through the `set-title` channel, this function will
|
||||
find the BrowserWindow instance attached to the message sender and use the `win.setTitle`
|
||||
API on it.
|
||||
|
||||
:::info
|
||||
Make sure you're loading the `index.html` and `preload.js` entry points for the following steps!
|
||||
:::
|
||||
|
||||
### 2. Expose `ipcRenderer.send` via preload
|
||||
|
||||
To send messages to the listener created above, you can use the `ipcRenderer.send` API.
|
||||
By default, the renderer process has no Node.js or Electron module access. As an app developer,
|
||||
you need to choose which APIs to expose from your preload script using the `contextBridge` API.
|
||||
|
||||
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)'
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
setTitle: (title) => ipcRenderer.send('set-title', title)
|
||||
})
|
||||
```
|
||||
|
||||
At this point, you'll be able to use the `window.electronAPI.setTitle()` function in the renderer
|
||||
process.
|
||||
|
||||
:::caution Security warning
|
||||
We don't directly expose the whole `ipcRenderer.send` API for [security reasons]. Make sure to
|
||||
limit the renderer's access to Electron APIs as much as possible.
|
||||
:::
|
||||
|
||||
### 3. Build the renderer process UI
|
||||
|
||||
In our BrowserWindow's loaded HTML file, add a basic user interface consisting of a text input
|
||||
and a button:
|
||||
|
||||
```html {11-12} title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
<body>
|
||||
Title: <input id="title"/>
|
||||
<button id="btn" type="button">Set</button>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
To make these elements interactive, we'll be adding a few lines of code in the imported
|
||||
`renderer.js` file that leverages the `window.electronAPI` functionality exposed from the preload
|
||||
script:
|
||||
|
||||
```javascript title='renderer.js (Renderer Process)'
|
||||
const setButton = document.getElementById('btn')
|
||||
const titleInput = document.getElementById('title')
|
||||
setButton.addEventListener('click', () => {
|
||||
const title = titleInput.value
|
||||
window.electronAPI.setTitle(title)
|
||||
});
|
||||
```
|
||||
|
||||
At this point, your demo should be fully functional. Try using the input field and see what happens
|
||||
to your BrowserWindow title!
|
||||
|
||||
## Pattern 2: Renderer to main (two-way)
|
||||
|
||||
A common application for two-way IPC is calling a main process module from your renderer process
|
||||
code and waiting for a result. This can be done by using [`ipcRenderer.invoke`] paired with
|
||||
[`ipcMain.handle`].
|
||||
|
||||
In the following example, we'll be opening a native file dialog from the renderer process and
|
||||
returning the selected file's path.
|
||||
|
||||
For this demo, you'll need to add code to your main process, your renderer process, and a preload
|
||||
script. The full code is below, but we'll be explaining each file individually in the following
|
||||
sections.
|
||||
|
||||
```fiddle docs/fiddles/ipc/pattern-2
|
||||
```
|
||||
|
||||
### 1. Listen for events with `ipcMain.handle`
|
||||
|
||||
In the main process, we'll be creating a `handleFileOpen()` function that calls
|
||||
`dialog.showOpenDialog` and returns the value of the file path selected by the user. This function
|
||||
is used as a callback whenever an `ipcRender.invoke` message is sent through the `dialog:openFile`
|
||||
channel from the renderer process. The return value is then returned as a Promise to the original
|
||||
`invoke` call.
|
||||
|
||||
:::caution A word on error handling
|
||||
Errors thrown through `handle` in the main process are not transparent as they
|
||||
are serialized and only the `message` property from the original error is
|
||||
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)'
|
||||
const { BrowserWindow, dialog, ipcMain } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
//...
|
||||
|
||||
async function handleFileOpen() {
|
||||
const { canceled, filePaths } = await dialog.showOpenDialog()
|
||||
if (canceled) {
|
||||
return
|
||||
} else {
|
||||
return filePaths[0]
|
||||
}
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady(() => {
|
||||
ipcMain.handle('dialog:openFile', handleFileOpen)
|
||||
createWindow()
|
||||
})
|
||||
//...
|
||||
```
|
||||
|
||||
:::tip on channel names
|
||||
The `dialog:` prefix on the IPC channel name has no effect on the code. It only serves
|
||||
as a namespace that helps with code readability.
|
||||
:::
|
||||
|
||||
:::info
|
||||
Make sure you're loading the `index.html` and `preload.js` entry points for the following steps!
|
||||
:::
|
||||
|
||||
### 2. Expose `ipcRenderer.invoke` via preload
|
||||
|
||||
In the preload script, we expose a one-line `openFile` function that calls and returns the value of
|
||||
`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)'
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
openFile: () => ipcRenderer.invoke('dialog:openFile')
|
||||
})
|
||||
```
|
||||
|
||||
:::caution Security warning
|
||||
We don't directly expose the whole `ipcRenderer.invoke` API for [security reasons]. Make sure to
|
||||
limit the renderer's access to Electron APIs as much as possible.
|
||||
:::
|
||||
|
||||
### 3. Build the renderer process UI
|
||||
|
||||
Finally, let's build the HTML file that we load into our BrowserWindow.
|
||||
|
||||
```html {10-11} title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Dialog</title>
|
||||
</head>
|
||||
<body>
|
||||
<button type="button" id="btn">Open a File</button>
|
||||
File path: <strong id="filePath"></strong>
|
||||
<script src='./renderer.js'></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
The UI consists of a single `#btn` button element that will be used to trigger our preload API, and
|
||||
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)'
|
||||
const btn = document.getElementById('btn')
|
||||
const filePathElement = document.getElementById('filePath')
|
||||
|
||||
btn.addEventListener('click', async () => {
|
||||
const filePath = await window.electronAPI.openFile()
|
||||
filePathElement.innerText = filePath
|
||||
})
|
||||
```
|
||||
|
||||
In the above snippet, we listen for clicks on the `#btn` button, and call our
|
||||
`window.electronAPI.openFile()` API to activate the native Open File dialog. We then display the
|
||||
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.
|
||||
|
||||
:::warning Avoid legacy approaches if possible
|
||||
We recommend using `ipcRenderer.invoke` whenever possible. The following two-way renderer-to-main
|
||||
patterns are documented for historical purposes.
|
||||
:::
|
||||
|
||||
:::info
|
||||
For the following examples, we're calling `ipcRenderer` directly from the preload script to keep
|
||||
the code samples small.
|
||||
:::
|
||||
|
||||
#### Using `ipcRenderer.send`
|
||||
|
||||
The `ipcRenderer.send` API that we used for single-way communication can also be leveraged to
|
||||
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)'
|
||||
// You can also put expose this code to the renderer
|
||||
// process with the `contextBridge` API
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
ipcRenderer.on('asynchronous-reply', (_event, arg) => {
|
||||
console.log(arg) // prints "pong" in the DevTools console
|
||||
})
|
||||
ipcRenderer.send('asynchronous-message', 'ping')
|
||||
```
|
||||
|
||||
```javascript 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
|
||||
// to the renderer that sent the original message
|
||||
event.reply('asynchronous-reply', 'pong')
|
||||
})
|
||||
```
|
||||
|
||||
There are a couple downsides to this approach:
|
||||
|
||||
* You need to set up a second `ipcRenderer.on` listener to handle the response in the renderer
|
||||
process. With `invoke`, you get the response value returned as a Promise to the original API call.
|
||||
* There's no obvious way to pair the `asynchronous-reply` message to the original
|
||||
`asynchronous-message` one. If you have very frequent messages going back and forth through these
|
||||
channels, you would need to add additional app code to track each call and response individually.
|
||||
|
||||
#### Using `ipcRenderer.sendSync`
|
||||
|
||||
The `ipcRenderer.sendSync` API sends a message to the main process and waits _synchronously_ for a
|
||||
response.
|
||||
|
||||
```javascript title='main.js (Main Process)'
|
||||
const { ipcMain } = require('electron')
|
||||
ipcMain.on('synchronous-message', (event, arg) => {
|
||||
console.log(arg) // prints "ping" in the Node console
|
||||
event.returnValue = 'pong'
|
||||
})
|
||||
```
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
// You can also put expose this code to the renderer
|
||||
// process with the `contextBridge` API
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
const result = ipcRenderer.sendSync('synchronous-message', 'ping')
|
||||
console.log(result) // prints "pong" in the DevTools console
|
||||
```
|
||||
|
||||
The structure of this code is very similar to the `invoke` model, but we recommend
|
||||
**avoiding this API** for performance reasons. Its synchronous nature means that it'll block the
|
||||
renderer process until a reply is received.
|
||||
|
||||
## Pattern 3: Main to renderer
|
||||
|
||||
When sending a message from the main process to a renderer process, you need to specify which
|
||||
renderer is receiving the message. Messages need to be sent to a renderer process
|
||||
via its [`WebContents`] instance. This WebContents instance contains a [`send`][webcontents-send] method
|
||||
that can be used in the same way as `ipcRenderer.send`.
|
||||
|
||||
To demonstrate this pattern, we'll be building a number counter controlled by the native operating
|
||||
system menu.
|
||||
|
||||
For this demo, you'll need to add code to your main process, your renderer process, and a preload
|
||||
script. The full code is below, but we'll be explaining each file individually in the following
|
||||
sections.
|
||||
|
||||
```fiddle docs/fiddles/ipc/pattern-3
|
||||
```
|
||||
|
||||
### 1. Send messages with the `webContents` module
|
||||
|
||||
For this demo, we'll need to first build a custom menu in the main process using Electron's `Menu`
|
||||
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)'
|
||||
const {app, BrowserWindow, Menu} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
const menu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: app.name,
|
||||
submenu: [
|
||||
{
|
||||
click: () => mainWindow.webContents.send('update-counter', 1),
|
||||
label: 'Increment',
|
||||
},
|
||||
{
|
||||
click: () => mainWindow.webContents.send('update-counter', -1),
|
||||
label: 'Decrement',
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
Menu.setApplicationMenu(menu)
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
//...
|
||||
|
||||
```
|
||||
|
||||
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 `counter` channel.
|
||||
|
||||
```javascript
|
||||
click: () => mainWindow.webContents.send('update-counter', -1)
|
||||
```
|
||||
|
||||
:::info
|
||||
Make sure you're loading the `index.html` and `preload.js` entry points for the following steps!
|
||||
:::
|
||||
|
||||
### 2. Expose `ipcRenderer.on` via preload
|
||||
|
||||
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)'
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', callback)
|
||||
})
|
||||
```
|
||||
|
||||
After loading the preload script, your renderer process should have access to the
|
||||
`window.electronAPI.onUpdateCounter()` listener function.
|
||||
|
||||
:::caution Security warning
|
||||
We don't directly expose the whole `ipcRenderer.on` API for [security reasons]. Make sure to
|
||||
limit the renderer's access to Electron APIs as much as possible.
|
||||
:::
|
||||
|
||||
:::info
|
||||
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)'
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const counter = document.getElementById('counter')
|
||||
ipcRenderer.on('update-counter', (_event, value) => {
|
||||
const oldValue = Number(counter.innerText)
|
||||
const newValue = oldValue + value
|
||||
counter.innerText = newValue
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
However, this approach has limited flexibility compared to exposing your preload APIs
|
||||
over the context bridge, since your listener can't directly interact with your renderer code.
|
||||
:::
|
||||
|
||||
### 3. Build the renderer process UI
|
||||
|
||||
To tie it all together, we'll create an interface in the loaded HTML file that contains a
|
||||
`#counter` element that we'll use to display the values:
|
||||
|
||||
```html {10} title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Menu Counter</title>
|
||||
</head>
|
||||
<body>
|
||||
Current value: <strong id="counter">0</strong>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
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)'
|
||||
const counter = document.getElementById('counter')
|
||||
|
||||
window.electronAPI.onUpdateCounter((_event, value) => {
|
||||
const oldValue = Number(counter.innerText)
|
||||
const newValue = oldValue + value
|
||||
counter.innerText = newValue
|
||||
})
|
||||
```
|
||||
|
||||
In the above code, we're passing in a callback to the `window.electronAPI.onUpdateCounter` function
|
||||
exposed from our preload script. The second `value` parameter corresponds to the `1` or `-1` we
|
||||
were passing in from the `webContents.send` call from the native menu.
|
||||
|
||||
### Optional: returning a reply
|
||||
|
||||
There's no equivalent for `ipcRenderer.invoke` for main-to-renderer IPC. Instead, you can
|
||||
send a reply back to the main process from within the `ipcRenderer.on` callback.
|
||||
|
||||
We can demonstrate this with slight modifications to the code from the previous example. In the
|
||||
renderer process, use the `event` parameter to send a reply back to the main process through the
|
||||
`counter-value` channel.
|
||||
|
||||
```javascript title='renderer.js (Renderer Process)'
|
||||
const counter = document.getElementById('counter')
|
||||
|
||||
window.electronAPI.onUpdateCounter((event, value) => {
|
||||
const oldValue = Number(counter.innerText)
|
||||
const newValue = oldValue + value
|
||||
counter.innerText = newValue
|
||||
event.reply('counter-value', newValue)
|
||||
})
|
||||
```
|
||||
|
||||
In the main process, listen for `counter-value` events and handle them appropriately.
|
||||
|
||||
```javascript title='main.js (Main Process)'
|
||||
//...
|
||||
ipcMain.on('counter-value', (_event, value) => {
|
||||
console.log(value) // will print value to Node console
|
||||
})
|
||||
//...
|
||||
```
|
||||
|
||||
## Pattern 4: Renderer to renderer
|
||||
|
||||
There's no direct way to send messages between renderer processes in Electron using the `ipcMain`
|
||||
and `ipcRenderer` modules. To achieve this, you have two options:
|
||||
|
||||
* Use the main process as a message broker between renderers. This would involve sending a message
|
||||
from one renderer to the main process, which would forward the message to the other renderer.
|
||||
* Pass a [MessagePort] from the main process to both renderers. This will allow direct communication
|
||||
between renderers after the initial setup.
|
||||
|
||||
## Object serialization
|
||||
|
||||
Electron's IPC implementation uses the HTML standard
|
||||
[Structured Clone Algorithm][sca] to serialize objects passed between processes, meaning that
|
||||
only certain types of objects can be passed through IPC channels.
|
||||
|
||||
In particular, DOM objects (e.g. `Element`, `Location` and `DOMMatrix`), Node.js objects
|
||||
backed by C++ classes (e.g. `process.env`, some members of `Stream`), and Electron objects
|
||||
backed by C++ classes (e.g. `WebContents`, `BrowserWindow` and `WebFrame`) are not serializable
|
||||
with Structured Clone.
|
||||
|
||||
[context isolation tutorial]: context-isolation.md
|
||||
[security reasons]: ./context-isolation.md#security-considerations
|
||||
[`ipcMain`]: ../api/ipc-main.md
|
||||
[`ipcMain.handle`]: ../api/ipc-main.md#ipcmainhandlechannel-listener
|
||||
[`ipcMain.on`]: ../api/ipc-main.md
|
||||
[IpcMainEvent]: ../api/structures/ipc-main-event.md
|
||||
[`ipcRenderer`]: ../api/ipc-renderer.md
|
||||
[`ipcRenderer.invoke`]: ../api/ipc-renderer.md#ipcrendererinvokechannel-args
|
||||
[`ipcRenderer.send`]: ../api/ipc-renderer.md
|
||||
[MessagePort]: ./message-ports.md
|
||||
[preload script]: process-model.md#preload-scripts
|
||||
[process model docs]: process-model.md
|
||||
[sca]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
||||
[`WebContents`]: ../api/web-contents.md
|
||||
[webcontents-send]: ../api/web-contents.md#contentssendchannel-args
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
title: Launching Your Electron App From a URL In Another App
|
||||
description: This guide will take you through the process of setting your electron app as the default handler for a specific protocol.
|
||||
title: Deep Links
|
||||
description: Set your Electron app as the default handler for a specific protocol.
|
||||
slug: launch-app-from-url-in-another-app
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Launching Your Electron App From A URL In Another App
|
||||
# Deep Links
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
# Desktop Launcher Actions (Linux)
|
||||
---
|
||||
title: Desktop Launcher Actions
|
||||
description: Add actions to the system launcher on Linux environments.
|
||||
slug: linux-desktop-actions
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Desktop Launcher Actions
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -42,4 +49,4 @@ parameters. You can find them in your application in the global variable
|
||||
|
||||
[unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher
|
||||
[audacious-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles?action=AttachFile&do=get&target=shortcuts.png
|
||||
[spec]: https://specifications.freedesktop.org/desktop-entry-spec/1.1/ar01s11.html
|
||||
[spec]: https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
# Dock (macOS)
|
||||
---
|
||||
title: Dock
|
||||
description: Configure your application's Dock presence on macOS.
|
||||
slug: macos-dock
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Dock
|
||||
|
||||
Electron has APIs to configure the app's icon in the macOS Dock. A macOS-only
|
||||
API exists to create a custom dock menu, but Electron also uses the app dock
|
||||
@@ -16,12 +23,6 @@ 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.
|
||||
|
||||
## Example
|
||||
|
||||
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/macos-dock-menu'
|
||||
const { app, BrowserWindow, Menu } = require('electron')
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ desktop environment that follows [Desktop Notifications
|
||||
Specification][notification-spec], including Cinnamon, Enlightenment, Unity,
|
||||
GNOME, KDE.
|
||||
|
||||
[notification-spec]: https://developer.gnome.org/notification-spec/
|
||||
[notification-spec]: https://developer-old.gnome.org/notification-spec/
|
||||
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
|
||||
[set-app-user-model-id]: ../api/app.md#appsetappusermodelidid-windows
|
||||
[squirrel-events]: https://github.com/electron/windows-installer/blob/master/README.md#handling-squirrel-events
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
---
|
||||
title: Performance
|
||||
description: A set of guidelines for building performant Electron apps
|
||||
slug: performance
|
||||
hide_title: true
|
||||
toc_max_heading_level: 3
|
||||
---
|
||||
|
||||
# Performance
|
||||
|
||||
Developers frequently ask about strategies to optimize the performance of
|
||||
@@ -49,7 +57,7 @@ at once, consider the [Chrome Tracing](https://www.chromium.org/developers/how-t
|
||||
* [Get Started With Analyzing Runtime Performance][chrome-devtools-tutorial]
|
||||
* [Talk: "Visual Studio Code - The First Second"][vscode-first-second]
|
||||
|
||||
## Checklist
|
||||
## Checklist: Performance recommendations
|
||||
|
||||
Chances are that your app could be a little leaner, faster, and generally less
|
||||
resource-hungry if you attempt these steps.
|
||||
@@ -62,7 +70,7 @@ resource-hungry if you attempt these steps.
|
||||
6. [Unnecessary or blocking network requests](#6-unnecessary-or-blocking-network-requests)
|
||||
7. [Bundle your code](#7-bundle-your-code)
|
||||
|
||||
## 1) Carelessly including modules
|
||||
### 1. Carelessly including modules
|
||||
|
||||
Before adding a Node.js module to your application, examine said module. How
|
||||
many dependencies does that module include? What kind of resources does
|
||||
@@ -70,7 +78,7 @@ it need to simply be called in a `require()` statement? You might find
|
||||
that the module with the most downloads on the NPM package registry or the most stars on GitHub
|
||||
is not in fact the leanest or smallest one available.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
The reasoning behind this recommendation is best illustrated with a real-world
|
||||
example. During the early days of Electron, reliable detection of network
|
||||
@@ -99,7 +107,7 @@ running Linux might be bad news for your app's performance. In this particular
|
||||
example, the correct solution was to use no module at all, and to instead use
|
||||
connectivity checks included in later versions of Chromium.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
When considering a module, we recommend that you check:
|
||||
|
||||
@@ -128,7 +136,7 @@ In this example, on the author's machine, we saw that loading `request` took
|
||||
almost half a second, whereas `node-fetch` took dramatically less memory
|
||||
and less than 50ms.
|
||||
|
||||
## 2) Loading and running code too soon
|
||||
### 2. Loading and running code too soon
|
||||
|
||||
If you have expensive setup operations, consider deferring those. Inspect all
|
||||
the work being executed right after the application starts. Instead of firing
|
||||
@@ -141,7 +149,7 @@ using the same strategy _and_ are using sizable modules that you do not
|
||||
immediately need, apply the same strategy and defer loading to a more
|
||||
opportune time.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Loading modules is a surprisingly expensive operation, especially on Windows.
|
||||
When your app starts, it should not make users wait for operations that are
|
||||
@@ -157,14 +165,14 @@ immediately display the file to you without any code highlighting, prioritizing
|
||||
your ability to interact with the text. Once it has done that work, it will
|
||||
move on to code highlighting.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
Let's consider an example and assume that your application is parsing files
|
||||
in the fictitious `.foo` format. In order to do that, it relies on the
|
||||
equally fictitious `foo-parser` module. In traditional Node.js development,
|
||||
you might write code that eagerly loads dependencies:
|
||||
|
||||
```js
|
||||
```js title='parser.js'
|
||||
const fs = require('fs')
|
||||
const fooParser = require('foo-parser')
|
||||
|
||||
@@ -187,7 +195,7 @@ In the above example, we're doing a lot of work that's being executed as soon
|
||||
as the file is loaded. Do we need to get parsed files right away? Could we
|
||||
do this work a little later, when `getParsedFiles()` is actually called?
|
||||
|
||||
```js
|
||||
```js title='parser.js'
|
||||
// "fs" is likely already being loaded, so the `require()` call is cheap
|
||||
const fs = require('fs')
|
||||
|
||||
@@ -223,7 +231,7 @@ module.exports = { parser }
|
||||
In short, allocate resources "just in time" rather than allocating them all
|
||||
when your app starts.
|
||||
|
||||
## 3) Blocking the main process
|
||||
### 3. Blocking the main process
|
||||
|
||||
Electron's main process (sometimes called "browser process") is special: It is
|
||||
the parent process to all your app's other processes and the primary process
|
||||
@@ -235,7 +243,7 @@ Under no circumstances should you block this process and the UI thread with
|
||||
long-running operations. Blocking the UI thread means that your entire app
|
||||
will freeze until the main process is ready to continue processing.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
The main process and its UI thread are essentially the control tower for major
|
||||
operations inside your app. When the operating system tells your app about a
|
||||
@@ -246,31 +254,31 @@ the GPU process about that – once again going through the main process.
|
||||
Electron and Chromium are careful to put heavy disk I/O and CPU-bound operations
|
||||
onto new threads to avoid blocking the UI thread. You should do the same.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
Electron's powerful multi-process architecture stands ready to assist you with
|
||||
your long-running tasks, but also includes a small number of performance traps.
|
||||
|
||||
1) For long running CPU-heavy tasks, make use of
|
||||
1. For long running CPU-heavy tasks, make use of
|
||||
[worker threads][worker-threads], consider moving them to the BrowserWindow, or
|
||||
(as a last resort) spawn a dedicated process.
|
||||
|
||||
2) Avoid using the synchronous IPC and the `remote` module as much as possible.
|
||||
While there are legitimate use cases, it is far too easy to unknowingly block
|
||||
the UI thread using the `remote` module.
|
||||
2. Avoid using the synchronous IPC and the `@electron/remote` module as much
|
||||
as possible. While there are legitimate use cases, it is far too easy to
|
||||
unknowingly block the UI thread.
|
||||
|
||||
3) Avoid using blocking I/O operations in the main process. In short, whenever
|
||||
3. Avoid using blocking I/O operations in the main process. In short, whenever
|
||||
core Node.js modules (like `fs` or `child_process`) offer a synchronous or an
|
||||
asynchronous version, you should prefer the asynchronous and non-blocking
|
||||
variant.
|
||||
|
||||
## 4) Blocking the renderer process
|
||||
### 4. Blocking the renderer process
|
||||
|
||||
Since Electron ships with a current version of Chrome, you can make use of the
|
||||
latest and greatest features the Web Platform offers to defer or offload heavy
|
||||
operations in a way that keeps your app smooth and responsive.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Your app probably has a lot of JavaScript to run in the renderer process. The
|
||||
trick is to execute operations as quickly as possible without taking away
|
||||
@@ -280,7 +288,7 @@ at 60fps.
|
||||
Orchestrating the flow of operations in your renderer's code is
|
||||
particularly useful if users complain about your app sometimes "stuttering".
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
Generally speaking, all advice for building performant web apps for modern
|
||||
browsers apply to Electron's renderers, too. The two primary tools at your
|
||||
@@ -300,14 +308,14 @@ some caveats to consider – consult Electron's
|
||||
for any operation that requires a lot of CPU power for an extended period of
|
||||
time.
|
||||
|
||||
## 5) Unnecessary polyfills
|
||||
### 5. Unnecessary polyfills
|
||||
|
||||
One of Electron's great benefits is that you know exactly which engine will
|
||||
parse your JavaScript, HTML, and CSS. If you're re-purposing code that was
|
||||
written for the web at large, make sure to not polyfill features included in
|
||||
Electron.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
When building a web application for today's Internet, the oldest environments
|
||||
dictate what features you can and cannot use. Even though Electron supports
|
||||
@@ -323,7 +331,7 @@ It is rare for a JavaScript-based polyfill to be faster than the equivalent
|
||||
native feature in Electron. Do not slow down your Electron app by shipping your
|
||||
own version of standard web platform features.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
Operate under the assumption that polyfills in current versions of Electron
|
||||
are unnecessary. If you have doubts, check [caniuse.com](https://caniuse.com/)
|
||||
@@ -338,12 +346,12 @@ If you're using a transpiler/compiler like TypeScript, examine its configuration
|
||||
and ensure that you're targeting the latest ECMAScript version supported by
|
||||
Electron.
|
||||
|
||||
## 6) Unnecessary or blocking network requests
|
||||
### 6. Unnecessary or blocking network requests
|
||||
|
||||
Avoid fetching rarely changing resources from the internet if they could easily
|
||||
be bundled with your application.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Many users of Electron start with an entirely web-based app that they're
|
||||
turning into a desktop application. As web developers, we are used to loading
|
||||
@@ -360,7 +368,7 @@ will take care of the rest.
|
||||
When building an Electron app, your users are better served if you download
|
||||
the fonts and include them in your app's bundle.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
In an ideal world, your application wouldn't need the network to operate at
|
||||
all. To get there, you must understand what resources your app is downloading
|
||||
@@ -387,21 +395,21 @@ without shipping an application update is a powerful strategy. For advanced
|
||||
control over how resources are being loaded, consider investing in
|
||||
[Service Workers][service-workers].
|
||||
|
||||
## 7) Bundle your code
|
||||
### 7. Bundle your code
|
||||
|
||||
As already pointed out in
|
||||
"[Loading and running code too soon](#2-loading-and-running-code-too-soon)",
|
||||
calling `require()` is an expensive operation. If you are able to do so,
|
||||
bundle your application's code into a single file.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Modern JavaScript development usually involves many files and modules. While
|
||||
that's perfectly fine for developing with Electron, we heavily recommend that
|
||||
you bundle all your code into one single file to ensure that the overhead
|
||||
included in calling `require()` is only paid once when your application loads.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
There are numerous JavaScript bundlers out there and we know better than to
|
||||
anger the community by recommending one tool over another. We do however
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
# Taskbar Progress Bar (Windows & macOS)
|
||||
---
|
||||
title: Progress Bars
|
||||
description: Provide progress information to users outside of a BrowserWindow.
|
||||
slug: progress-bar
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Progress Bars
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -463,46 +463,46 @@ The fastest way to distribute your newly created app is using
|
||||
1. Add Electron Forge as a development dependency of your app, and use its `import` command to set up
|
||||
Forge's scaffolding:
|
||||
|
||||
```sh npm2yarn
|
||||
npm install --save-dev @electron-forge/cli
|
||||
npx electron-forge import
|
||||
```sh npm2yarn
|
||||
npm install --save-dev @electron-forge/cli
|
||||
npx electron-forge import
|
||||
|
||||
✔ Checking your system
|
||||
✔ Initializing Git Repository
|
||||
✔ Writing modified package.json file
|
||||
✔ Installing dependencies
|
||||
✔ Writing modified package.json file
|
||||
✔ Fixing .gitignore
|
||||
✔ Checking your system
|
||||
✔ Initializing Git Repository
|
||||
✔ Writing modified package.json file
|
||||
✔ Installing dependencies
|
||||
✔ Writing modified package.json file
|
||||
✔ Fixing .gitignore
|
||||
|
||||
We have ATTEMPTED to convert your app to be in a format that electron-forge understands.
|
||||
We have ATTEMPTED to convert your app to be in a format that electron-forge understands.
|
||||
|
||||
Thanks for using "electron-forge"!!!
|
||||
```
|
||||
Thanks for using "electron-forge"!!!
|
||||
```
|
||||
|
||||
1. Create a distributable using Forge's `make` command:
|
||||
2. Create a distributable using Forge's `make` command:
|
||||
|
||||
```sh npm2yarn
|
||||
npm run make
|
||||
```sh npm2yarn
|
||||
npm run make
|
||||
|
||||
> my-electron-app@1.0.0 make /my-electron-app
|
||||
> electron-forge make
|
||||
> my-electron-app@1.0.0 make /my-electron-app
|
||||
> electron-forge make
|
||||
|
||||
✔ Checking your system
|
||||
✔ Resolving Forge Config
|
||||
We need to package your application before we can make it
|
||||
✔ Preparing to Package Application for arch: x64
|
||||
✔ Preparing native dependencies
|
||||
✔ Packaging Application
|
||||
Making for the following targets: zip
|
||||
✔ Making for target: zip - On platform: darwin - For arch: x64
|
||||
```
|
||||
✔ Checking your system
|
||||
✔ Resolving Forge Config
|
||||
We need to package your application before we can make it
|
||||
✔ Preparing to Package Application for arch: x64
|
||||
✔ Preparing native dependencies
|
||||
✔ Packaging Application
|
||||
Making for the following targets: zip
|
||||
✔ Making for target: zip - On platform: darwin - For arch: x64
|
||||
```
|
||||
|
||||
Electron Forge creates the `out` folder where your package will be located:
|
||||
Electron Forge creates the `out` folder where your package will be located:
|
||||
|
||||
```plain
|
||||
// Example for macOS
|
||||
out/
|
||||
├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
|
||||
├── ...
|
||||
└── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app
|
||||
```
|
||||
```plain
|
||||
// Example for macOS
|
||||
out/
|
||||
├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
|
||||
├── ...
|
||||
└── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app
|
||||
```
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
# Recent Documents (Windows & macOS)
|
||||
---
|
||||
title: Recent Documents
|
||||
description: Provide a list of recent documents via Windows JumpList or macOS Dock
|
||||
slug: recent-documents
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Recent Documents
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
# Representing Files in a BrowserWindow (macOS)
|
||||
---
|
||||
title: Representing Files in a BrowserWindow
|
||||
description: Set a represented file in the macOS title bar.
|
||||
slug: represented-file
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Representing Files in a BrowserWindow
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -1,6 +1,24 @@
|
||||
# Security, Native Capabilities, and Your Responsibility
|
||||
---
|
||||
title: Security
|
||||
description: A set of guidelines for building secure Electron apps
|
||||
slug: security
|
||||
hide_title: true
|
||||
toc_max_heading_level: 3
|
||||
---
|
||||
# Security
|
||||
|
||||
As web developers, we usually enjoy the strong security net of the browser -
|
||||
:::info Reporting security issues
|
||||
For information on how to properly disclose an Electron vulnerability,
|
||||
see [SECURITY.md](https://github.com/electron/electron/tree/main/SECURITY.md).
|
||||
|
||||
For upstream Chromium vulnerabilities: Electron keeps up to date with alternating
|
||||
Chromium releases. For more information, see the
|
||||
[Electron Release Timelines](../tutorial/electron-timelines.md) document.
|
||||
:::
|
||||
|
||||
## Preface
|
||||
|
||||
As web developers, we usually enjoy the strong security net of the browser —
|
||||
the risks associated with the code we write are relatively small. Our websites
|
||||
are granted limited powers in a sandbox, and we trust that our users enjoy a
|
||||
browser built by a large team of engineers that is able to quickly respond to
|
||||
@@ -17,20 +35,12 @@ With that in mind, be aware that displaying arbitrary content from untrusted
|
||||
sources poses a severe security risk that Electron is not intended to handle.
|
||||
In fact, the most popular Electron apps (Atom, Slack, Visual Studio Code, etc)
|
||||
display primarily local content (or trusted, secure remote content without Node
|
||||
integration) – if your application executes code from an online source, it is
|
||||
integration) — if your application executes code from an online source, it is
|
||||
your responsibility to ensure that the code is not malicious.
|
||||
|
||||
## Reporting Security Issues
|
||||
## General guidelines
|
||||
|
||||
For information on how to properly disclose an Electron vulnerability,
|
||||
see [SECURITY.md](https://github.com/electron/electron/tree/main/SECURITY.md)
|
||||
|
||||
## Chromium Security Issues and Upgrades
|
||||
|
||||
Electron keeps up to date with alternating Chromium releases. For more information,
|
||||
see the [Electron Release Cadence blog post](https://electronjs.org/blog/12-week-cadence).
|
||||
|
||||
## Security Is Everyone's Responsibility
|
||||
### Security is everyone's responsibility
|
||||
|
||||
It is important to remember that the security of your Electron application is
|
||||
the result of the overall security of the framework foundation
|
||||
@@ -56,7 +66,7 @@ is your own code. Common web vulnerabilities, such as Cross-Site Scripting (XSS)
|
||||
have a higher security impact on Electron applications hence it is highly recommended
|
||||
to adopt secure software development best practices and perform security testing.
|
||||
|
||||
## Isolation For Untrusted Content
|
||||
### Isolation for untrusted content
|
||||
|
||||
A security issue exists whenever you receive code from an untrusted source (e.g.
|
||||
a remote server) and execute it locally. As an example, consider a remote
|
||||
@@ -65,72 +75,74 @@ an attacker somehow manages to change said content (either by attacking the
|
||||
source directly, or by sitting between your app and the actual destination), they
|
||||
will be able to execute native code on the user's machine.
|
||||
|
||||
> :warning: Under no circumstances should you load and execute remote code with
|
||||
:::warning
|
||||
Under no circumstances should you load and execute remote code with
|
||||
Node.js integration enabled. Instead, use only local files (packaged together
|
||||
with your application) to execute Node.js code. To display remote content, use
|
||||
the [`<webview>`][webview-tag] tag or [`BrowserView`][browser-view], make sure
|
||||
to disable the `nodeIntegration` and enable `contextIsolation`.
|
||||
:::
|
||||
|
||||
## Electron Security Warnings
|
||||
|
||||
From Electron 2.0 on, developers will see warnings and recommendations printed
|
||||
to the developer console. They only show up when the binary's name is Electron,
|
||||
indicating that a developer is currently looking at the console.
|
||||
:::info Electron security warnings
|
||||
Security warnings and recommendations are printed to the developer console.
|
||||
They only show up when the binary's name is Electron, indicating that a developer
|
||||
is currently looking at the console.
|
||||
|
||||
You can force-enable or force-disable these warnings by setting
|
||||
`ELECTRON_ENABLE_SECURITY_WARNINGS` or `ELECTRON_DISABLE_SECURITY_WARNINGS` on
|
||||
either `process.env` or the `window` object.
|
||||
:::
|
||||
|
||||
## Checklist: Security Recommendations
|
||||
## Checklist: Security recommendations
|
||||
|
||||
You should at least follow these steps to improve the security of your application:
|
||||
|
||||
1. [Only load secure content](#1-only-load-secure-content)
|
||||
2. [Disable the Node.js integration in all renderers that display remote content](#2-do-not-enable-nodejs-integration-for-remote-content)
|
||||
3. [Enable context isolation in all renderers that display remote content](#3-enable-context-isolation-for-remote-content)
|
||||
4. [Enable sandboxing](#4-enable-sandboxing)
|
||||
4. [Enable process sandboxing](#4-enable-process-sandboxing)
|
||||
5. [Use `ses.setPermissionRequestHandler()` in all sessions that load remote content](#5-handle-session-permission-requests-from-remote-content)
|
||||
6. [Do not disable `webSecurity`](#6-do-not-disable-websecurity)
|
||||
7. [Define a `Content-Security-Policy`](#7-define-a-content-security-policy) and use restrictive rules (i.e. `script-src 'self'`)
|
||||
8. [Do not set `allowRunningInsecureContent` to `true`](#8-do-not-set-allowrunninginsecurecontent-to-true)
|
||||
8. [Do not enable `allowRunningInsecureContent`](#8-do-not-enable-allowrunninginsecurecontent)
|
||||
9. [Do not enable experimental features](#9-do-not-enable-experimental-features)
|
||||
10. [Do not use `enableBlinkFeatures`](#10-do-not-use-enableblinkfeatures)
|
||||
11. [`<webview>`: Do not use `allowpopups`](#11-do-not-use-allowpopups)
|
||||
11. [`<webview>`: Do not use `allowpopups`](#11-do-not-use-allowpopups-for-webviews)
|
||||
12. [`<webview>`: Verify options and params](#12-verify-webview-options-before-creation)
|
||||
13. [Disable or limit navigation](#13-disable-or-limit-navigation)
|
||||
14. [Disable or limit creation of new windows](#14-disable-or-limit-creation-of-new-windows)
|
||||
15. [Do not use `openExternal` with untrusted content](#15-do-not-use-openexternal-with-untrusted-content)
|
||||
15. [Do not use `shell.openExternal` with untrusted content](#15-do-not-use-shellopenexternal-with-untrusted-content)
|
||||
16. [Use a current version of Electron](#16-use-a-current-version-of-electron)
|
||||
|
||||
To automate the detection of misconfigurations and insecure patterns, it is
|
||||
possible to use
|
||||
[electronegativity](https://github.com/doyensec/electronegativity). For
|
||||
[Electronegativity](https://github.com/doyensec/electronegativity). For
|
||||
additional details on potential weaknesses and implementation bugs when
|
||||
developing applications using Electron, please refer to this [guide for
|
||||
developers and auditors](https://doyensec.com/resources/us-17-Carettoni-Electronegativity-A-Study-Of-Electron-Security-wp.pdf)
|
||||
developers and auditors](https://doyensec.com/resources/us-17-Carettoni-Electronegativity-A-Study-Of-Electron-Security-wp.pdf).
|
||||
|
||||
## 1) Only Load Secure Content
|
||||
### 1. Only load secure content
|
||||
|
||||
Any resources not included with your application should be loaded using a
|
||||
secure protocol like `HTTPS`. In other words, do not use insecure protocols
|
||||
like `HTTP`. Similarly, we recommend the use of `WSS` over `WS`, `FTPS` over
|
||||
`FTP`, and so on.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
`HTTPS` has three main benefits:
|
||||
|
||||
1) It authenticates the remote server, ensuring your app connects to the correct
|
||||
1. It authenticates the remote server, ensuring your app connects to the correct
|
||||
host instead of an impersonator.
|
||||
2) It ensures data integrity, asserting that the data was not modified while in
|
||||
1. It ensures data integrity, asserting that the data was not modified while in
|
||||
transit between your application and the host.
|
||||
3) It encrypts the traffic between your user and the destination host, making it
|
||||
1. It encrypts the traffic between your user and the destination host, making it
|
||||
more difficult to eavesdrop on the information sent between your app and
|
||||
the host.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
browserWindow.loadURL('http://example.com')
|
||||
|
||||
@@ -138,7 +150,7 @@ browserWindow.loadURL('http://example.com')
|
||||
browserWindow.loadURL('https://example.com')
|
||||
```
|
||||
|
||||
```html
|
||||
```html title='index.html (Renderer Process)'
|
||||
<!-- Bad -->
|
||||
<script crossorigin src="http://example.com/react.js"></script>
|
||||
<link rel="stylesheet" href="http://example.com/style.css">
|
||||
@@ -148,9 +160,11 @@ browserWindow.loadURL('https://example.com')
|
||||
<link rel="stylesheet" href="https://example.com/style.css">
|
||||
```
|
||||
|
||||
## 2) Do not enable Node.js Integration for Remote Content
|
||||
### 2. Do not enable Node.js integration for remote content
|
||||
|
||||
_This recommendation is the default behavior in Electron since 5.0.0._
|
||||
:::info
|
||||
This recommendation is the default behavior in Electron since 5.0.0.
|
||||
:::
|
||||
|
||||
It is paramount that you do not enable Node.js integration in any renderer
|
||||
([`BrowserWindow`][browser-window], [`BrowserView`][browser-view], or
|
||||
@@ -163,7 +177,7 @@ After this, you can grant additional permissions for specific hosts. For example
|
||||
if you are opening a BrowserWindow pointed at `https://example.com/`, you can
|
||||
give that website exactly the abilities it needs, but no more.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
A cross-site-scripting (XSS) attack is more dangerous if an attacker can jump
|
||||
out of the renderer process and execute code on the user's computer.
|
||||
@@ -172,12 +186,13 @@ power is usually limited to messing with the website that they are executed on.
|
||||
Disabling Node.js integration helps prevent an XSS from being escalated into a
|
||||
so-called "Remote Code Execution" (RCE) attack.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
contextIsolation: false,
|
||||
nodeIntegration: true,
|
||||
nodeIntegrationInWorker: true
|
||||
}
|
||||
@@ -186,7 +201,7 @@ const mainWindow = new BrowserWindow({
|
||||
mainWindow.loadURL('https://example.com')
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Good
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
@@ -197,7 +212,7 @@ const mainWindow = new BrowserWindow({
|
||||
mainWindow.loadURL('https://example.com')
|
||||
```
|
||||
|
||||
```html
|
||||
```html title='index.html (Renderer Process)'
|
||||
<!-- Bad -->
|
||||
<webview nodeIntegration src="page.html"></webview>
|
||||
|
||||
@@ -208,21 +223,13 @@ mainWindow.loadURL('https://example.com')
|
||||
When disabling Node.js integration, you can still expose APIs to your website that
|
||||
do consume Node.js modules or features. Preload scripts continue to have access
|
||||
to `require` and other Node.js features, allowing developers to expose a custom
|
||||
API to remotely loaded content.
|
||||
API to remotely loaded content via the [contextBridge API](../api/context-bridge.md).
|
||||
|
||||
In the following example preload script, the later loaded website will have
|
||||
access to a `window.readConfig()` method, but no Node.js features.
|
||||
### 3. Enable Context Isolation for remote content
|
||||
|
||||
```js
|
||||
const { readFileSync } = require('fs')
|
||||
|
||||
window.readConfig = () => {
|
||||
const data = readFileSync('./config.json')
|
||||
return data
|
||||
}
|
||||
```
|
||||
|
||||
## 3) Enable Context Isolation for Remote Content
|
||||
:::info
|
||||
This recommendation is the default behavior in Electron since 12.0.0.
|
||||
:::
|
||||
|
||||
Context isolation is an Electron feature that allows developers to run code
|
||||
in preload scripts and in Electron APIs in a dedicated JavaScript context. In
|
||||
@@ -235,48 +242,42 @@ to enable this behavior.
|
||||
Even when `nodeIntegration: false` is used, to truly enforce strong isolation
|
||||
and prevent the use of Node primitives `contextIsolation` **must** also be used.
|
||||
|
||||
### Why & How?
|
||||
|
||||
:::info
|
||||
For more information on what `contextIsolation` is and how to enable it please
|
||||
see our dedicated [Context Isolation](context-isolation.md) document.
|
||||
:::info
|
||||
|
||||
## 4) Enable Sandboxing
|
||||
### 4. Enable process sandboxing
|
||||
|
||||
[Sandboxing](sandbox.md) is a Chromium feature that uses the operating system to
|
||||
[Sandboxing](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox.md)
|
||||
is a Chromium feature that uses the operating system to
|
||||
significantly limit what renderer processes have access to. You should enable
|
||||
the sandbox in all renderers. Loading, reading or processing any untrusted
|
||||
content in an unsandboxed process, including the main process, is not advised.
|
||||
|
||||
### How?
|
||||
:::info
|
||||
For more information on what `contextIsolation` is and how to enable it please
|
||||
see our dedicated [Process Sandboxing](sandbox.md) document.
|
||||
:::info
|
||||
|
||||
When creating a window, pass the `sandbox: true` option in `webPreferences`:
|
||||
### 5. Handle session permission requests from remote content
|
||||
|
||||
```js
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
sandbox: true
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 5) Handle Session Permission Requests From Remote Content
|
||||
|
||||
You may have seen permission requests while using Chrome: They pop up whenever
|
||||
You may have seen permission requests while using Chrome: they pop up whenever
|
||||
the website attempts to use a feature that the user has to manually approve (
|
||||
like notifications).
|
||||
|
||||
The API is based on the [Chromium permissions API](https://developer.chrome.com/extensions/permissions)
|
||||
and implements the same types of permissions.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
By default, Electron will automatically approve all permission requests unless
|
||||
the developer has manually configured a custom handler. While a solid default,
|
||||
security-conscious developers might want to assume the very opposite.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
const { session } = require('electron')
|
||||
|
||||
session
|
||||
@@ -297,9 +298,11 @@ session
|
||||
})
|
||||
```
|
||||
|
||||
## 6) Do Not Disable WebSecurity
|
||||
### 6. Do not disable `webSecurity`
|
||||
|
||||
_Recommendation is Electron's default_
|
||||
:::info
|
||||
This recommendation is Electron's default.
|
||||
:::
|
||||
|
||||
You may have already guessed that disabling the `webSecurity` property on a
|
||||
renderer process ([`BrowserWindow`][browser-window],
|
||||
@@ -308,15 +311,15 @@ security features.
|
||||
|
||||
Do not disable `webSecurity` in production applications.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Disabling `webSecurity` will disable the same-origin policy and set
|
||||
`allowRunningInsecureContent` property to `true`. In other words, it allows
|
||||
the execution of insecure code from different domains.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
@@ -325,12 +328,12 @@ const mainWindow = new BrowserWindow({
|
||||
})
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Good
|
||||
const mainWindow = new BrowserWindow()
|
||||
```
|
||||
|
||||
```html
|
||||
```html title='index.html (Renderer Process)'
|
||||
<!-- Bad -->
|
||||
<webview disablewebsecurity src="page.html"></webview>
|
||||
|
||||
@@ -338,13 +341,13 @@ const mainWindow = new BrowserWindow()
|
||||
<webview src="page.html"></webview>
|
||||
```
|
||||
|
||||
## 7) Define a Content Security Policy
|
||||
### 7. Define a Content Security Policy
|
||||
|
||||
A Content Security Policy (CSP) is an additional layer of protection against
|
||||
cross-site-scripting attacks and data injection attacks. We recommend that they
|
||||
be enabled by any website you load inside Electron.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
CSP allows the server serving content to restrict and control the resources
|
||||
Electron can load for that given web page. `https://example.com` should
|
||||
@@ -352,6 +355,8 @@ be allowed to load scripts from the origins you defined while scripts from
|
||||
`https://evil.attacker.com` should not be allowed to run. Defining a CSP is an
|
||||
easy way to improve your application's security.
|
||||
|
||||
#### How?
|
||||
|
||||
The following CSP will allow Electron to execute scripts from the current
|
||||
website and from `apis.example.com`.
|
||||
|
||||
@@ -363,14 +368,14 @@ Content-Security-Policy: '*'
|
||||
Content-Security-Policy: script-src 'self' https://apis.example.com
|
||||
```
|
||||
|
||||
### CSP HTTP Header
|
||||
#### CSP HTTP headers
|
||||
|
||||
Electron respects the [`Content-Security-Policy` HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy)
|
||||
which can be set using Electron's
|
||||
[`webRequest.onHeadersReceived`](../api/web-request.md#webrequestonheadersreceivedfilter-listener)
|
||||
handler:
|
||||
|
||||
```javascript
|
||||
```javascript title='main.js (Main Process)'
|
||||
const { session } = require('electron')
|
||||
|
||||
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
|
||||
@@ -383,20 +388,22 @@ session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
|
||||
})
|
||||
```
|
||||
|
||||
### CSP Meta Tag
|
||||
#### CSP meta tag
|
||||
|
||||
CSP's preferred delivery mechanism is an HTTP header, however it is not possible
|
||||
CSP's preferred delivery mechanism is an HTTP header. However, it is not possible
|
||||
to use this method when loading a resource using the `file://` protocol. It can
|
||||
be useful in some cases, such as using the `file://` protocol, to set a policy
|
||||
on a page directly in the markup using a `<meta>` tag:
|
||||
be useful in some cases to set a policy on a page directly in the markup using a
|
||||
`<meta>` tag:
|
||||
|
||||
```html
|
||||
```html title='index.html (Renderer Process)'
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'">
|
||||
```
|
||||
|
||||
## 8) Do Not Set `allowRunningInsecureContent` to `true`
|
||||
### 8. Do not enable `allowRunningInsecureContent`
|
||||
|
||||
_Recommendation is Electron's default_
|
||||
:::info
|
||||
This recommendation is Electron's default.
|
||||
:::
|
||||
|
||||
By default, Electron will not allow websites loaded over `HTTPS` to load and
|
||||
execute scripts, CSS, or plugins from insecure sources (`HTTP`). Setting the
|
||||
@@ -405,15 +412,15 @@ property `allowRunningInsecureContent` to `true` disables that protection.
|
||||
Loading the initial HTML of a website over `HTTPS` and attempting to load
|
||||
subsequent resources via `HTTP` is also known as "mixed content".
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Loading content over `HTTPS` assures the authenticity and integrity
|
||||
of the loaded resources while encrypting the traffic itself. See the section on
|
||||
[only displaying secure content](#1-only-load-secure-content) for more details.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
@@ -422,19 +429,21 @@ const mainWindow = new BrowserWindow({
|
||||
})
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Good
|
||||
const mainWindow = new BrowserWindow({})
|
||||
```
|
||||
|
||||
## 9) Do Not Enable Experimental Features
|
||||
### 9. Do not enable experimental features
|
||||
|
||||
_Recommendation is Electron's default_
|
||||
:::info
|
||||
This recommendation is Electron's default.
|
||||
:::
|
||||
|
||||
Advanced users of Electron can enable experimental Chromium features using the
|
||||
`experimentalFeatures` property.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Experimental features are, as the name suggests, experimental and have not been
|
||||
enabled for all Chromium users. Furthermore, their impact on Electron as a whole
|
||||
@@ -443,9 +452,9 @@ has likely not been tested.
|
||||
Legitimate use cases exist, but unless you know what you are doing, you should
|
||||
not enable this property.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
@@ -454,20 +463,22 @@ const mainWindow = new BrowserWindow({
|
||||
})
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Good
|
||||
const mainWindow = new BrowserWindow({})
|
||||
```
|
||||
|
||||
## 10) Do Not Use `enableBlinkFeatures`
|
||||
### 10. Do not use `enableBlinkFeatures`
|
||||
|
||||
_Recommendation is Electron's default_
|
||||
:::info
|
||||
This recommendation is Electron's default.
|
||||
:::
|
||||
|
||||
Blink is the name of the rendering engine behind Chromium. As with
|
||||
`experimentalFeatures`, the `enableBlinkFeatures` property allows developers to
|
||||
enable features that have been disabled by default.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Generally speaking, there are likely good reasons if a feature was not enabled
|
||||
by default. Legitimate use cases for enabling specific features exist. As a
|
||||
@@ -475,9 +486,9 @@ developer, you should know exactly why you need to enable a feature, what the
|
||||
ramifications are, and how it impacts the security of your application. Under
|
||||
no circumstances should you enable features speculatively.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
@@ -486,14 +497,16 @@ const mainWindow = new BrowserWindow({
|
||||
})
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Good
|
||||
const mainWindow = new BrowserWindow()
|
||||
```
|
||||
|
||||
## 11) Do Not Use `allowpopups`
|
||||
### 11. Do not use `allowpopups` for WebViews
|
||||
|
||||
_Recommendation is Electron's default_
|
||||
:::info
|
||||
This recommendation is Electron's default.
|
||||
:::
|
||||
|
||||
If you are using [`<webview>`][webview-tag], you might need the pages and scripts
|
||||
loaded in your `<webview>` tag to open new windows. The `allowpopups` attribute
|
||||
@@ -501,16 +514,16 @@ enables them to create new [`BrowserWindows`][browser-window] using the
|
||||
`window.open()` method. `<webview>` tags are otherwise not allowed to create new
|
||||
windows.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
If you do not need popups, you are better off not allowing the creation of
|
||||
new [`BrowserWindows`][browser-window] by default. This follows the principle
|
||||
of minimally required access: Don't let a website create new popups unless
|
||||
you know it needs that feature.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```html
|
||||
```html title='index.html (Renderer Process)'
|
||||
<!-- Bad -->
|
||||
<webview allowpopups src="page.html"></webview>
|
||||
|
||||
@@ -518,7 +531,7 @@ you know it needs that feature.
|
||||
<webview src="page.html"></webview>
|
||||
```
|
||||
|
||||
## 12) Verify WebView Options Before Creation
|
||||
### 12. Verify WebView options before creation
|
||||
|
||||
A WebView created in a renderer process that does not have Node.js integration
|
||||
enabled will not be able to enable integration itself. However, a WebView will
|
||||
@@ -528,7 +541,7 @@ It is a good idea to control the creation of new [`<webview>`][webview-tag] tags
|
||||
from the main process and to verify that their webPreferences do not disable
|
||||
security features.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Since `<webview>` live in the DOM, they can be created by a script running on your
|
||||
website even if Node.js integration is otherwise disabled.
|
||||
@@ -538,13 +551,13 @@ a renderer process. In most cases, developers do not need to disable any of
|
||||
those features - and you should therefore not allow different configurations
|
||||
for newly created [`<webview>`][webview-tag] tags.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
Before a [`<webview>`][webview-tag] tag is attached, Electron will fire the
|
||||
`will-attach-webview` event on the hosting `webContents`. Use the event to
|
||||
prevent the creation of `webViews` with possibly insecure options.
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
app.on('web-contents-created', (event, contents) => {
|
||||
contents.on('will-attach-webview', (event, webPreferences, params) => {
|
||||
// Strip away preload scripts if unused or verify their location is legitimate
|
||||
@@ -562,16 +575,16 @@ app.on('web-contents-created', (event, contents) => {
|
||||
})
|
||||
```
|
||||
|
||||
Again, this list merely minimizes the risk, it does not remove it. If your goal
|
||||
Again, this list merely minimizes the risk, but does not remove it. If your goal
|
||||
is to display a website, a browser will be a more secure option.
|
||||
|
||||
## 13) Disable or limit navigation
|
||||
### 13. Disable or limit navigation
|
||||
|
||||
If your app has no need to navigate or only needs to navigate to known pages,
|
||||
it is a good idea to limit navigation outright to that known scope, disallowing
|
||||
any other kinds of navigation.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Navigation is a common attack vector. If an attacker can convince your app to
|
||||
navigate away from its current page, they can possibly force your app to open
|
||||
@@ -584,7 +597,7 @@ A common attack pattern is that the attacker convinces your app's users to
|
||||
interact with the app in such a way that it navigates to one of the attacker's
|
||||
pages. This is usually done via links, plugins, or other user-generated content.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
If your app has no need for navigation, you can call `event.preventDefault()`
|
||||
in a [`will-navigate`][will-navigate] handler. If you know which pages your app
|
||||
@@ -595,7 +608,7 @@ We recommend that you use Node's parser for URLs. Simple string comparisons can
|
||||
sometimes be fooled - a `startsWith('https://example.com')` test would let
|
||||
`https://example.com.attacker.com` through.
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
const URL = require('url').URL
|
||||
|
||||
app.on('web-contents-created', (event, contents) => {
|
||||
@@ -609,12 +622,12 @@ app.on('web-contents-created', (event, contents) => {
|
||||
})
|
||||
```
|
||||
|
||||
## 14) Disable or limit creation of new windows
|
||||
### 14. Disable or limit creation of new windows
|
||||
|
||||
If you have a known set of windows, it's a good idea to limit the creation of
|
||||
additional windows in your app.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Much like navigation, the creation of new `webContents` is a common attack
|
||||
vector. Attackers attempt to convince your app to create new windows, frames,
|
||||
@@ -627,7 +640,7 @@ security at no cost. This is commonly the case for apps that open one
|
||||
`BrowserWindow` and do not need to open an arbitrary number of additional
|
||||
windows at runtime.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
[`webContents`][web-contents] will delegate to its [window open
|
||||
handler][window-open-handler] before creating new windows. The handler will
|
||||
@@ -635,7 +648,7 @@ receive, amongst other parameters, the `url` the window was requested to open
|
||||
and the options used to create it. We recommend that you register a handler to
|
||||
monitor the creation of windows, and deny any unexpected window creation.
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
const { shell } = require('electron')
|
||||
|
||||
app.on('web-contents-created', (event, contents) => {
|
||||
@@ -656,40 +669,40 @@ app.on('web-contents-created', (event, contents) => {
|
||||
})
|
||||
```
|
||||
|
||||
## 15) Do not use `openExternal` with untrusted content
|
||||
### 15. Do not use `shell.openExternal` with untrusted content
|
||||
|
||||
Shell's [`openExternal`][open-external] allows opening a given protocol URI with
|
||||
the desktop's native utilities. On macOS, for instance, this function is similar
|
||||
to the `open` terminal command utility and will open the specific application
|
||||
based on the URI and filetype association.
|
||||
The shell module's [`openExternal`][open-external] API allows opening a given
|
||||
protocol URI with the desktop's native utilities. On macOS, for instance, this
|
||||
function is similar to the `open` terminal command utility and will open the
|
||||
specific application based on the URI and filetype association.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
Improper use of [`openExternal`][open-external] can be leveraged to compromise
|
||||
the user's host. When openExternal is used with untrusted content, it can be
|
||||
leveraged to execute arbitrary commands.
|
||||
|
||||
### How?
|
||||
#### How?
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Bad
|
||||
const { shell } = require('electron')
|
||||
shell.openExternal(USER_CONTROLLED_DATA_HERE)
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='main.js (Main Process)'
|
||||
// Good
|
||||
const { shell } = require('electron')
|
||||
shell.openExternal('https://example.com/index.html')
|
||||
```
|
||||
|
||||
## 16) Use a current version of Electron
|
||||
### 16. Use a current version of Electron
|
||||
|
||||
You should strive for always using the latest available version of Electron.
|
||||
Whenever a new major version is released, you should attempt to update your
|
||||
app as quickly as possible.
|
||||
|
||||
### Why?
|
||||
#### Why?
|
||||
|
||||
An application built with an older version of Electron, Chromium, and Node.js
|
||||
is an easier target than an application that is using more recent versions of
|
||||
@@ -705,6 +718,13 @@ to fix issues before publishing them. Your application will be more secure if
|
||||
it is running a recent version of Electron (and thus, Chromium and Node.js) for
|
||||
which potential security issues are not as widely known.
|
||||
|
||||
#### How?
|
||||
|
||||
Migrate your app one major version at a time, while referring to Electron's
|
||||
[Breaking Changes][breaking-changes] document to see if any code needs to
|
||||
be updated.
|
||||
|
||||
[breaking-changes]: ../breaking-changes.md
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[browser-view]: ../api/browser-view.md
|
||||
[webview-tag]: ../api/webview-tag.md
|
||||
@@ -712,5 +732,4 @@ which potential security issues are not as widely known.
|
||||
[window-open-handler]: ../api/web-contents.md#contentssetwindowopenhandlerhandler
|
||||
[will-navigate]: ../api/web-contents.md#event-will-navigate
|
||||
[open-external]: ../api/shell.md#shellopenexternalurl-options
|
||||
[sandbox]: ../tutorial/sandbox.md
|
||||
[responsible-disclosure]: https://en.wikipedia.org/wiki/Responsible_disclosure
|
||||
|
||||
@@ -1,128 +1,5 @@
|
||||
# Electron Support
|
||||
# This doc has moved!
|
||||
|
||||
## Finding Support
|
||||
|
||||
If you have a security concern,
|
||||
please see the [security document](https://github.com/electron/electron/tree/main/SECURITY.md).
|
||||
|
||||
If you're looking for programming help,
|
||||
for answers to questions,
|
||||
or to join in discussion with other developers who use Electron,
|
||||
you can interact with the community in these locations:
|
||||
|
||||
* [Electron's Discord server](https://discord.com/invite/APGC3k5yaH) has channels for:
|
||||
* Getting help
|
||||
* Ecosystem apps like [Electron Forge](https://github.com/electron-userland/electron-forge) and [Electron Fiddle](https://github.com/electron/fiddle)
|
||||
* Sharing ideas with other Electron app developers
|
||||
* And more!
|
||||
* [`electron`](https://discuss.atom.io/c/electron) category on the Atom forums
|
||||
* `#electron` channel on [Atom's Slack](https://discuss.atom.io/t/join-us-on-slack/16638?source_topic_id=25406)
|
||||
* [`electron-ru`](https://telegram.me/electron_ru) *(Russian)*
|
||||
* [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
* [`electron-kr`](https://electron-kr.github.io/electron-kr) *(Korean)*
|
||||
* [`electron-jp`](https://electron-jp.slack.com) *(Japanese)*
|
||||
* [`electron-tr`](https://electron-tr.herokuapp.com) *(Turkish)*
|
||||
* [`electron-id`](https://electron-id.slack.com) *(Indonesia)*
|
||||
* [`electron-pl`](https://electronpl.github.io) *(Poland)*
|
||||
|
||||
If you'd like to contribute to Electron,
|
||||
see the [contributing document](https://github.com/electron/electron/blob/main/CONTRIBUTING.md).
|
||||
|
||||
If you've found a bug in a [supported version](#supported-versions) of Electron,
|
||||
please report it with the [issue tracker](../development/issues.md).
|
||||
|
||||
[awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
is a community-maintained list of useful example apps,
|
||||
tools and resources.
|
||||
|
||||
## Supported Versions
|
||||
|
||||
_**Note:** Beginning in September 2021 with Electron 15, the Electron team
|
||||
will temporarily support the latest **four** stable major versions. This
|
||||
extended support is intended to help Electron developers transition to
|
||||
the [new eight week release cadence](https://electronjs.org/blog/8-week-cadence), and will continue until May 2022, with
|
||||
the release of Electron 19. At that time, 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
|
||||
for each stable release series. This means that in the case of a security fix
|
||||
6.1.x will receive the fix, but we will not release a new version of 6.0.x.
|
||||
|
||||
The latest stable release unilaterally receives all fixes from `main`,
|
||||
and the version prior to that receives the vast majority of those fixes
|
||||
as time and bandwidth warrants. The oldest supported release line will receive
|
||||
only security fixes directly.
|
||||
|
||||
All supported release lines will accept external pull requests to backport
|
||||
fixes previously merged to `main`, though this may be on a case-by-case
|
||||
basis for some older supported lines. All contested decisions around release
|
||||
line backports will be resolved by the [Releases Working Group](https://github.com/electron/governance/tree/main/wg-releases) as an agenda item at their weekly meeting the week the backport PR is raised.
|
||||
|
||||
When an API is changed or removed in a way that breaks existing functionality, the
|
||||
previous functionality will be supported for a minimum of two major versions when
|
||||
possible before being removed. For example, if a function takes three arguments,
|
||||
and that number is reduced to two in major version 10, the three-argument version would
|
||||
continue to work until, at minimum, major version 12. Past the minimum two-version
|
||||
threshold, we will attempt to support backwards compatibility beyond two versions
|
||||
until the maintainers feel the maintenance burden is too high to continue doing so.
|
||||
|
||||
### Currently supported versions
|
||||
|
||||
* 18.x.y
|
||||
* 17.x.y
|
||||
* 16.x.y
|
||||
* 15.x.y
|
||||
|
||||
### End-of-life
|
||||
|
||||
When a release branch reaches the end of its support cycle, the series
|
||||
will be deprecated in NPM and a final end-of-support release will be
|
||||
made. This release will add a warning to inform that an unsupported
|
||||
version of Electron is in use.
|
||||
|
||||
These steps are to help app developers learn when a branch they're
|
||||
using becomes unsupported, but without being excessively intrusive
|
||||
to end users.
|
||||
|
||||
If an application has exceptional circumstances and needs to stay
|
||||
on an unsupported series of Electron, developers can silence the
|
||||
end-of-support warning by omitting the final release from the app's
|
||||
`package.json` `devDependencies`. For example, since the 1-6-x series
|
||||
ended with an end-of-support 1.6.18 release, developers could choose
|
||||
to stay in the 1-6-x series without warnings with `devDependency` of
|
||||
`"electron": 1.6.0 - 1.6.17`.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
Following platforms are supported by Electron:
|
||||
|
||||
### macOS
|
||||
|
||||
Only 64bit binaries are provided for macOS, and the minimum macOS version
|
||||
supported is macOS 10.11 (El Capitan).
|
||||
|
||||
Native support for Apple Silicon (`arm64`) devices was added in Electron 11.0.0.
|
||||
|
||||
### Windows
|
||||
|
||||
Windows 7 and later are supported, older operating systems are not supported
|
||||
(and do not work).
|
||||
|
||||
Both `ia32` (`x86`) and `x64` (`amd64`) binaries are provided for Windows.
|
||||
[Native support for Windows on Arm (`arm64`) devices was added in Electron 6.0.8.](windows-arm.md).
|
||||
Running apps packaged with previous versions is possible using the ia32 binary.
|
||||
|
||||
### Linux
|
||||
|
||||
The prebuilt binaries of Electron are built on Ubuntu 18.04.
|
||||
|
||||
Whether the prebuilt binary can run on a distribution depends on whether the
|
||||
distribution includes the libraries that Electron is linked to on the building
|
||||
platform, so only Ubuntu 18.04 is guaranteed to work, but following platforms
|
||||
are also verified to be able to run the prebuilt binaries of Electron:
|
||||
|
||||
* Ubuntu 14.04 and newer
|
||||
* Fedora 24 and newer
|
||||
* Debian 8 and newer
|
||||
* For information on supported releases, see the [Electron Releases](./electron-timelines.md) doc.
|
||||
* For community support on Electron, see the [Community page](https://www.electronjs.org/community).
|
||||
* For platform support info, see the [README](https://github.com/electron/electron/blob/main/README.md).
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Being based on Chromium, Electron requires a display driver to function.
|
||||
If Chromium can't find a display driver, Electron will fail to launch -
|
||||
and therefore not executing any of your tests, regardless of how you are running
|
||||
them. Testing Electron-based apps on Travis, Circle, Jenkins or similar Systems
|
||||
them. Testing Electron-based apps on Travis, CircleCI, Jenkins or similar Systems
|
||||
requires therefore a little bit of configuration. In essence, we need to use
|
||||
a virtual display driver.
|
||||
|
||||
@@ -49,10 +49,9 @@ install:
|
||||
|
||||
For Jenkins, a [Xvfb plugin is available](https://wiki.jenkins-ci.org/display/JENKINS/Xvfb+Plugin).
|
||||
|
||||
### Circle CI
|
||||
### CircleCI
|
||||
|
||||
Circle CI is awesome and has Xvfb and `$DISPLAY`
|
||||
[already set up, so no further configuration is required](https://circleci.com/docs/environment#browsers).
|
||||
CircleCI is awesome and has Xvfb and `$DISPLAY` already set up, so no further configuration is required.
|
||||
|
||||
### AppVeyor
|
||||
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
# Taskbar Customization (Windows)
|
||||
---
|
||||
title: Taskbar Customization
|
||||
description: Customize the look and feel of your app's Windows taskbar presence.
|
||||
slug: windows-taskbar
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Taskbar Customization
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -179,6 +179,7 @@ template("electron_paks") {
|
||||
"${root_gen_dir}/device/bluetooth/strings/bluetooth_strings_",
|
||||
"${root_gen_dir}/services/strings/services_strings_",
|
||||
"${root_gen_dir}/ui/strings/app_locale_settings_",
|
||||
"${root_gen_dir}/ui/strings/ax_strings_",
|
||||
"${root_gen_dir}/ui/strings/ui_strings_",
|
||||
]
|
||||
deps = [
|
||||
@@ -188,16 +189,17 @@ template("electron_paks") {
|
||||
"//services/strings",
|
||||
"//third_party/blink/public/strings",
|
||||
"//ui/strings:app_locale_settings",
|
||||
"//ui/strings:ax_strings",
|
||||
"//ui/strings:ui_strings",
|
||||
]
|
||||
|
||||
input_locales = locales
|
||||
input_locales = platform_pak_locales
|
||||
output_dir = "${invoker.output_dir}/locales"
|
||||
|
||||
if (is_mac) {
|
||||
output_locales = locales_as_mac_outputs
|
||||
} else {
|
||||
output_locales = locales
|
||||
output_locales = platform_pak_locales
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,11 +100,14 @@ auto_filenames = {
|
||||
"docs/api/structures/new-window-web-contents-event.md",
|
||||
"docs/api/structures/notification-action.md",
|
||||
"docs/api/structures/notification-response.md",
|
||||
"docs/api/structures/payment-discount.md",
|
||||
"docs/api/structures/point.md",
|
||||
"docs/api/structures/post-body.md",
|
||||
"docs/api/structures/printer-info.md",
|
||||
"docs/api/structures/process-memory-info.md",
|
||||
"docs/api/structures/process-metric.md",
|
||||
"docs/api/structures/product-discount.md",
|
||||
"docs/api/structures/product-subscription-period.md",
|
||||
"docs/api/structures/product.md",
|
||||
"docs/api/structures/protocol-request.md",
|
||||
"docs/api/structures/protocol-response-upload-data.md",
|
||||
|
||||
@@ -32,10 +32,13 @@ filenames = {
|
||||
"shell/browser/notifications/linux/notification_presenter_linux.cc",
|
||||
"shell/browser/notifications/linux/notification_presenter_linux.h",
|
||||
"shell/browser/relauncher_linux.cc",
|
||||
"shell/browser/ui/electron_desktop_window_tree_host_linux.cc",
|
||||
"shell/browser/ui/file_dialog_gtk.cc",
|
||||
"shell/browser/ui/message_box_gtk.cc",
|
||||
"shell/browser/ui/tray_icon_gtk.cc",
|
||||
"shell/browser/ui/tray_icon_gtk.h",
|
||||
"shell/browser/ui/views/client_frame_view_linux.cc",
|
||||
"shell/browser/ui/views/client_frame_view_linux.h",
|
||||
"shell/common/application_info_linux.cc",
|
||||
"shell/common/language_util_linux.cc",
|
||||
"shell/common/node_bindings_linux.cc",
|
||||
@@ -383,8 +386,6 @@ filenames = {
|
||||
"shell/browser/file_select_helper.cc",
|
||||
"shell/browser/file_select_helper.h",
|
||||
"shell/browser/file_select_helper_mac.mm",
|
||||
"shell/browser/font/electron_font_access_delegate.cc",
|
||||
"shell/browser/font/electron_font_access_delegate.h",
|
||||
"shell/browser/font_defaults.cc",
|
||||
"shell/browser/font_defaults.h",
|
||||
"shell/browser/hid/electron_hid_delegate.cc",
|
||||
@@ -413,6 +414,8 @@ filenames = {
|
||||
"shell/browser/native_browser_view.h",
|
||||
"shell/browser/native_window.cc",
|
||||
"shell/browser/native_window.h",
|
||||
"shell/browser/native_window_features.cc",
|
||||
"shell/browser/native_window_features.h",
|
||||
"shell/browser/native_window_observer.h",
|
||||
"shell/browser/net/asar/asar_file_validator.cc",
|
||||
"shell/browser/net/asar/asar_file_validator.h",
|
||||
@@ -676,8 +679,6 @@ filenames = {
|
||||
]
|
||||
|
||||
lib_sources_extensions = [
|
||||
"shell/browser/extensions/api/i18n/i18n_api.cc",
|
||||
"shell/browser/extensions/api/i18n/i18n_api.h",
|
||||
"shell/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc",
|
||||
"shell/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h",
|
||||
"shell/browser/extensions/api/management/electron_management_api_delegate.cc",
|
||||
@@ -734,11 +735,6 @@ filenames = {
|
||||
"shell/renderer/extensions/electron_extensions_renderer_client.h",
|
||||
]
|
||||
|
||||
app_sources = [
|
||||
"shell/app/electron_main.cc",
|
||||
"shell/app/electron_main.h",
|
||||
]
|
||||
|
||||
framework_sources = [
|
||||
"shell/app/electron_library_main.h",
|
||||
"shell/app/electron_library_main.mm",
|
||||
|
||||
@@ -35,7 +35,7 @@ const spawnUpdate = function (args: string[], detached: boolean, callback: Funct
|
||||
spawnedArgs = args || [];
|
||||
}
|
||||
} catch (error1) {
|
||||
error = error1;
|
||||
error = error1 as Error;
|
||||
|
||||
// Shouldn't happen, but still guard it.
|
||||
process.nextTick(function () {
|
||||
|
||||
@@ -61,24 +61,25 @@ class IncomingMessage extends Readable {
|
||||
const filteredHeaders: Record<string, string | string[]> = {};
|
||||
const { rawHeaders } = this._responseHead;
|
||||
rawHeaders.forEach(header => {
|
||||
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key) &&
|
||||
discardableDuplicateHeaders.has(header.key)) {
|
||||
const keyLowerCase = header.key.toLowerCase();
|
||||
if (Object.prototype.hasOwnProperty.call(filteredHeaders, keyLowerCase) &&
|
||||
discardableDuplicateHeaders.has(keyLowerCase)) {
|
||||
// do nothing with discardable duplicate headers
|
||||
} else {
|
||||
if (header.key === 'set-cookie') {
|
||||
if (keyLowerCase === 'set-cookie') {
|
||||
// keep set-cookie as an array per Node.js rules
|
||||
// see https://nodejs.org/api/http.html#http_message_headers
|
||||
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
|
||||
(filteredHeaders[header.key] as string[]).push(header.value);
|
||||
if (Object.prototype.hasOwnProperty.call(filteredHeaders, keyLowerCase)) {
|
||||
(filteredHeaders[keyLowerCase] as string[]).push(header.value);
|
||||
} else {
|
||||
filteredHeaders[header.key] = [header.value];
|
||||
filteredHeaders[keyLowerCase] = [header.value];
|
||||
}
|
||||
} else {
|
||||
// for non-cookie headers, the values are joined together with ', '
|
||||
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
|
||||
filteredHeaders[header.key] += `, ${header.value}`;
|
||||
if (Object.prototype.hasOwnProperty.call(filteredHeaders, keyLowerCase)) {
|
||||
filteredHeaders[keyLowerCase] += `, ${header.value}`;
|
||||
} else {
|
||||
filteredHeaders[header.key] = header.value;
|
||||
filteredHeaders[keyLowerCase] = header.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,6 +87,15 @@ class IncomingMessage extends Readable {
|
||||
return filteredHeaders;
|
||||
}
|
||||
|
||||
get rawHeaders () {
|
||||
const rawHeadersArr: string[] = [];
|
||||
const { rawHeaders } = this._responseHead;
|
||||
rawHeaders.forEach(header => {
|
||||
rawHeadersArr.push(header.key, header.value);
|
||||
});
|
||||
return rawHeadersArr;
|
||||
}
|
||||
|
||||
get httpVersion () {
|
||||
return `${this.httpVersionMajor}.${this.httpVersionMinor}`;
|
||||
}
|
||||
@@ -188,7 +198,7 @@ class ChunkedBodyStream extends Writable {
|
||||
this._downstream = pipe;
|
||||
if (this._pendingChunk) {
|
||||
const doneWriting = (maybeError: Error | void) => {
|
||||
// If the underlying request has been aborted, we honeslty don't care about the error
|
||||
// If the underlying request has been aborted, we honestly don't care about the error
|
||||
// all work should cease as soon as we abort anyway, this error is probably a
|
||||
// "mojo pipe disconnected" error (code=9)
|
||||
if (this._clientRequest._aborted) return;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { app, ipcMain, session, webFrameMain } from 'electron/main';
|
||||
import { app, ipcMain, session, webFrameMain, deprecate } from 'electron/main';
|
||||
import type { BrowserWindowConstructorOptions, LoadURLOptions } from 'electron/main';
|
||||
|
||||
import * as url from 'url';
|
||||
@@ -492,41 +492,51 @@ WebContents.prototype.loadURL = function (url, options) {
|
||||
return p;
|
||||
};
|
||||
|
||||
WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => ({action: 'allow'} | {action: 'deny', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions})) {
|
||||
WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => ({action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions, outlivesOpener?: boolean})) {
|
||||
this._windowOpenHandler = handler;
|
||||
};
|
||||
|
||||
WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): BrowserWindowConstructorOptions | null {
|
||||
WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): {browserWindowConstructorOptions: BrowserWindowConstructorOptions | null, outlivesOpener: boolean} {
|
||||
const defaultResponse = {
|
||||
browserWindowConstructorOptions: null,
|
||||
outlivesOpener: false
|
||||
};
|
||||
if (!this._windowOpenHandler) {
|
||||
return null;
|
||||
return defaultResponse;
|
||||
}
|
||||
const response = this._windowOpenHandler(details);
|
||||
|
||||
if (typeof response !== 'object') {
|
||||
event.preventDefault();
|
||||
console.error(`The window open handler response must be an object, but was instead of type '${typeof response}'.`);
|
||||
return null;
|
||||
return defaultResponse;
|
||||
}
|
||||
|
||||
if (response === null) {
|
||||
event.preventDefault();
|
||||
console.error('The window open handler response must be an object, but was instead null.');
|
||||
return null;
|
||||
return defaultResponse;
|
||||
}
|
||||
|
||||
if (response.action === 'deny') {
|
||||
event.preventDefault();
|
||||
return null;
|
||||
return defaultResponse;
|
||||
} else if (response.action === 'allow') {
|
||||
if (typeof response.overrideBrowserWindowOptions === 'object' && response.overrideBrowserWindowOptions !== null) {
|
||||
return response.overrideBrowserWindowOptions;
|
||||
return {
|
||||
browserWindowConstructorOptions: response.overrideBrowserWindowOptions,
|
||||
outlivesOpener: typeof response.outlivesOpener === 'boolean' ? response.outlivesOpener : false
|
||||
};
|
||||
} else {
|
||||
return {};
|
||||
return {
|
||||
browserWindowConstructorOptions: {},
|
||||
outlivesOpener: typeof response.outlivesOpener === 'boolean' ? response.outlivesOpener : false
|
||||
};
|
||||
}
|
||||
} else {
|
||||
event.preventDefault();
|
||||
console.error('The window open handler response must be an object with an \'action\' property of \'allow\' or \'deny\'.');
|
||||
return null;
|
||||
return defaultResponse;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -560,6 +570,10 @@ const loggingEnabled = () => {
|
||||
|
||||
// Add JavaScript wrappers for WebContents class.
|
||||
WebContents.prototype._init = function () {
|
||||
const prefs = this.getLastWebPreferences() || {};
|
||||
if (!prefs.nodeIntegration && (prefs.preload != null || prefs.preloadURL != null) && prefs.sandbox == null) {
|
||||
deprecate.log('The default sandbox option for windows without nodeIntegration is changing. Presently, by default, when a window has a preload script, it defaults to being unsandboxed. In Electron 20, this default will be changing, and all windows that have nodeIntegration: false (which is the default) will be sandboxed by default. If your preload script doesn\'t use Node, no action is needed. If your preload script does use Node, either refactor it to move Node usage to the main process, or specify sandbox: false in your WebPreferences.');
|
||||
}
|
||||
// Read off the ID at construction time, so that it's accessible even after
|
||||
// the underlying C++ WebContents is destroyed.
|
||||
const id = this.id;
|
||||
@@ -651,7 +665,8 @@ WebContents.prototype._init = function () {
|
||||
postBody,
|
||||
disposition
|
||||
};
|
||||
const options = this._callWindowOpenHandler(event, details);
|
||||
const result = this._callWindowOpenHandler(event, details);
|
||||
const options = result.browserWindowConstructorOptions;
|
||||
if (!event.defaultPrevented) {
|
||||
openGuestWindow({
|
||||
event,
|
||||
@@ -660,12 +675,14 @@ WebContents.prototype._init = function () {
|
||||
referrer,
|
||||
postData,
|
||||
overrideBrowserWindowOptions: options || {},
|
||||
windowOpenArgs: details
|
||||
windowOpenArgs: details,
|
||||
outlivesOpener: result.outlivesOpener
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let windowOpenOverriddenOptions: BrowserWindowConstructorOptions | null = null;
|
||||
let windowOpenOutlivesOpenerOption: boolean = false;
|
||||
this.on('-will-add-new-contents' as any, (event: ElectronInternal.Event, url: string, frameName: string, rawFeatures: string, disposition: Electron.HandlerDetails['disposition'], referrer: Electron.Referrer, postData: PostData) => {
|
||||
const postBody = postData ? {
|
||||
data: postData,
|
||||
@@ -679,7 +696,9 @@ WebContents.prototype._init = function () {
|
||||
referrer,
|
||||
postBody
|
||||
};
|
||||
windowOpenOverriddenOptions = this._callWindowOpenHandler(event, details);
|
||||
const result = this._callWindowOpenHandler(event, details);
|
||||
windowOpenOutlivesOpenerOption = result.outlivesOpener;
|
||||
windowOpenOverriddenOptions = result.browserWindowConstructorOptions;
|
||||
if (!event.defaultPrevented) {
|
||||
const secureOverrideWebPreferences = windowOpenOverriddenOptions ? {
|
||||
// Allow setting of backgroundColor as a webPreference even though
|
||||
@@ -710,7 +729,10 @@ WebContents.prototype._init = function () {
|
||||
_userGesture: boolean, _left: number, _top: number, _width: number, _height: number, url: string, frameName: string,
|
||||
referrer: Electron.Referrer, rawFeatures: string, postData: PostData) => {
|
||||
const overriddenOptions = windowOpenOverriddenOptions || undefined;
|
||||
const outlivesOpener = windowOpenOutlivesOpenerOption;
|
||||
windowOpenOverriddenOptions = null;
|
||||
// false is the default
|
||||
windowOpenOutlivesOpenerOption = false;
|
||||
|
||||
if ((disposition !== 'foreground-tab' && disposition !== 'new-window' &&
|
||||
disposition !== 'background-tab')) {
|
||||
@@ -730,7 +752,8 @@ WebContents.prototype._init = function () {
|
||||
url,
|
||||
frameName,
|
||||
features: rawFeatures
|
||||
}
|
||||
},
|
||||
outlivesOpener
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -73,6 +73,17 @@ function makeWebPreferences (embedder: Electron.WebContents, params: Record<stri
|
||||
return webPreferences;
|
||||
}
|
||||
|
||||
function makeLoadURLOptions (params: Record<string, any>) {
|
||||
const opts: Electron.LoadURLOptions = {};
|
||||
if (params.httpreferrer) {
|
||||
opts.httpReferrer = params.httpreferrer;
|
||||
}
|
||||
if (params.useragent) {
|
||||
opts.userAgent = params.useragent;
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
|
||||
// Create a new guest instance.
|
||||
const createGuest = function (embedder: Electron.WebContents, embedderFrameId: number, elementInstanceId: number, params: Record<string, any>) {
|
||||
// eslint-disable-next-line no-undef
|
||||
@@ -96,7 +107,7 @@ const createGuest = function (embedder: Electron.WebContents, embedderFrameId: n
|
||||
|
||||
// Init guest web view after attached.
|
||||
guest.once('did-attach' as any, function (this: Electron.WebContents, event: Electron.Event) {
|
||||
params = this.attachParams!;
|
||||
const params = this.attachParams!;
|
||||
delete this.attachParams;
|
||||
|
||||
const previouslyAttached = this.viewInstanceId != null;
|
||||
@@ -108,14 +119,7 @@ const createGuest = function (embedder: Electron.WebContents, embedderFrameId: n
|
||||
}
|
||||
|
||||
if (params.src) {
|
||||
const opts: Electron.LoadURLOptions = {};
|
||||
if (params.httpreferrer) {
|
||||
opts.httpReferrer = params.httpreferrer;
|
||||
}
|
||||
if (params.useragent) {
|
||||
opts.userAgent = params.useragent;
|
||||
}
|
||||
this.loadURL(params.src, opts);
|
||||
this.loadURL(params.src, params.opts);
|
||||
}
|
||||
embedder.emit('did-attach-webview', event, guest);
|
||||
});
|
||||
@@ -204,13 +208,15 @@ const attachGuest = function (embedder: Electron.WebContents, embedderFrameId: n
|
||||
return false;
|
||||
}
|
||||
|
||||
const { instanceId } = params;
|
||||
|
||||
// If this guest is already attached to an element then remove it
|
||||
if (guestInstance.elementInstanceId) {
|
||||
const oldKey = `${guestInstance.embedder.id}-${guestInstance.elementInstanceId}`;
|
||||
embedderElementsMap.delete(oldKey);
|
||||
|
||||
// Remove guest from embedder if moving across web views
|
||||
if (guest.viewInstanceId !== params.instanceId) {
|
||||
if (guest.viewInstanceId !== instanceId) {
|
||||
webViewManager.removeGuest(guestInstance.embedder, guestInstanceId);
|
||||
guestInstance.embedder._sendInternal(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DESTROY_GUEST}-${guest.viewInstanceId}`);
|
||||
}
|
||||
@@ -221,12 +227,12 @@ const attachGuest = function (embedder: Electron.WebContents, embedderFrameId: n
|
||||
const event = eventBinding.createWithSender(embedder);
|
||||
embedder.emit('will-attach-webview', event, webPreferences, params);
|
||||
if (event.defaultPrevented) {
|
||||
if (guest.viewInstanceId == null) guest.viewInstanceId = params.instanceId;
|
||||
if (guest.viewInstanceId == null) guest.viewInstanceId = instanceId;
|
||||
guest.destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
guest.attachParams = params;
|
||||
guest.attachParams = { instanceId, src: params.src, opts: makeLoadURLOptions(params) };
|
||||
embedderElementsMap.set(key, guestInstanceId);
|
||||
|
||||
guest.setEmbedder(embedder);
|
||||
|
||||
@@ -29,7 +29,7 @@ const getGuestWindowByFrameName = (name: string) => frameNamesToWindow.get(name)
|
||||
* user to preventDefault() on the passed event (which ends up calling
|
||||
* DestroyWebContents).
|
||||
*/
|
||||
export function openGuestWindow ({ event, embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs }: {
|
||||
export function openGuestWindow ({ event, embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs, outlivesOpener }: {
|
||||
event: { sender: WebContents, defaultPrevented: boolean },
|
||||
embedder: WebContents,
|
||||
guest?: WebContents,
|
||||
@@ -38,6 +38,7 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
|
||||
postData?: PostData,
|
||||
overrideBrowserWindowOptions?: BrowserWindowConstructorOptions,
|
||||
windowOpenArgs: WindowOpenArgs,
|
||||
outlivesOpener: boolean,
|
||||
}): BrowserWindow | undefined {
|
||||
const { url, frameName, features } = windowOpenArgs;
|
||||
const { options: browserWindowOptions } = makeBrowserWindowOptions({
|
||||
@@ -77,7 +78,7 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
|
||||
...browserWindowOptions
|
||||
});
|
||||
|
||||
handleWindowLifecycleEvents({ embedder, frameName, guest: window });
|
||||
handleWindowLifecycleEvents({ embedder, frameName, guest: window, outlivesOpener });
|
||||
|
||||
embedder.emit('did-create-window', window, { url, frameName, options: browserWindowOptions, disposition, referrer, postData });
|
||||
|
||||
@@ -90,10 +91,11 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
|
||||
* too is the guest destroyed; this is Electron convention and isn't based in
|
||||
* browser behavior.
|
||||
*/
|
||||
const handleWindowLifecycleEvents = function ({ embedder, guest, frameName }: {
|
||||
const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, outlivesOpener }: {
|
||||
embedder: WebContents,
|
||||
guest: BrowserWindow,
|
||||
frameName: string
|
||||
frameName: string,
|
||||
outlivesOpener: boolean
|
||||
}) {
|
||||
const closedByEmbedder = function () {
|
||||
guest.removeListener('closed', closedByUser);
|
||||
@@ -101,9 +103,14 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, frameName }: {
|
||||
};
|
||||
|
||||
const closedByUser = function () {
|
||||
embedder.removeListener('current-render-view-deleted' as any, closedByEmbedder);
|
||||
// Embedder might have been closed
|
||||
if (!embedder.isDestroyed() && !outlivesOpener) {
|
||||
embedder.removeListener('current-render-view-deleted' as any, closedByEmbedder);
|
||||
}
|
||||
};
|
||||
embedder.once('current-render-view-deleted' as any, closedByEmbedder);
|
||||
if (!outlivesOpener) {
|
||||
embedder.once('current-render-view-deleted' as any, closedByEmbedder);
|
||||
}
|
||||
guest.once('closed', closedByUser);
|
||||
|
||||
if (frameName) {
|
||||
@@ -163,7 +170,8 @@ function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs,
|
||||
handleWindowLifecycleEvents({
|
||||
embedder: event.sender,
|
||||
guest: newGuest,
|
||||
frameName
|
||||
frameName,
|
||||
outlivesOpener: false
|
||||
});
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -15,7 +15,7 @@ export class IpcMainImpl extends EventEmitter {
|
||||
try {
|
||||
e._reply(await Promise.resolve(fn(e, ...args)));
|
||||
} catch (err) {
|
||||
e._throw(err);
|
||||
e._throw(err as Error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,40 +8,24 @@ const { contextIsolationEnabled } = internalContextBridge;
|
||||
|
||||
/* Corrects for some Inspector adaptations needed in Electron.
|
||||
* 1) Use menu API to show context menu.
|
||||
* 2) Correct for Chromium returning undefined for filesystem.
|
||||
* 3) Use dialog API to override file chooser dialog.
|
||||
*/
|
||||
window.onload = function () {
|
||||
if (contextIsolationEnabled) {
|
||||
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
|
||||
'InspectorFrontendHost', 'showContextMenuAtPoint'
|
||||
], createMenu);
|
||||
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
|
||||
'Persistence', 'FileSystemWorkspaceBinding', 'completeURL'
|
||||
], completeURL);
|
||||
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
|
||||
'UI', 'createFileSelectorElement'
|
||||
], createFileSelectorElement);
|
||||
} else {
|
||||
window.InspectorFrontendHost!.showContextMenuAtPoint = createMenu;
|
||||
window.Persistence!.FileSystemWorkspaceBinding.completeURL = completeURL;
|
||||
window.UI!.createFileSelectorElement = createFileSelectorElement;
|
||||
}
|
||||
};
|
||||
|
||||
// Extra / is needed as a result of MacOS requiring absolute paths
|
||||
function completeURL (project: string, path: string) {
|
||||
project = 'file:///';
|
||||
return `${project}${path}`;
|
||||
}
|
||||
|
||||
// The DOM implementation expects (message?: string) => boolean
|
||||
window.confirm = function (message?: string, title?: string) {
|
||||
return ipcRendererUtils.invokeSync(IPC_MESSAGES.INSPECTOR_CONFIRM, message, title) as boolean;
|
||||
};
|
||||
|
||||
const useEditMenuItems = function (x: number, y: number, items: ContextMenuItem[]) {
|
||||
return items.length === 0 && document.elementsFromPoint(x, y).some(function (element) {
|
||||
return items.length === 0 && document.elementsFromPoint(x, y).some(element => {
|
||||
return element.nodeName === 'INPUT' ||
|
||||
element.nodeName === 'TEXTAREA' ||
|
||||
(element as HTMLElement).isContentEditable;
|
||||
@@ -58,22 +42,3 @@ const createMenu = function (x: number, y: number, items: ContextMenuItem[]) {
|
||||
webFrame.executeJavaScript('window.DevToolsAPI.contextMenuCleared()');
|
||||
});
|
||||
};
|
||||
|
||||
const showFileChooserDialog = function (callback: (blob: File) => void) {
|
||||
ipcRendererInternal.invoke<[ string, any ]>(IPC_MESSAGES.INSPECTOR_SELECT_FILE).then(([path, data]) => {
|
||||
if (path && data) {
|
||||
callback(dataToHtml5FileObject(path, data));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const dataToHtml5FileObject = function (path: string, data: any) {
|
||||
return new File([data], path);
|
||||
};
|
||||
|
||||
const createFileSelectorElement = function (this: any, callback: () => void) {
|
||||
const fileSelectorElement = document.createElement('span');
|
||||
fileSelectorElement.style.display = 'none';
|
||||
fileSelectorElement.click = showFileChooserDialog.bind(this, callback);
|
||||
return fileSelectorElement;
|
||||
};
|
||||
|
||||
@@ -25,7 +25,6 @@ export class WebViewImpl {
|
||||
public hasFocus = false
|
||||
public internalInstanceId?: number;
|
||||
public resizeObserver?: ResizeObserver;
|
||||
public userAgentOverride?: string;
|
||||
public viewInstanceId: number
|
||||
|
||||
// on* Event handlers.
|
||||
@@ -180,8 +179,7 @@ export class WebViewImpl {
|
||||
|
||||
buildParams () {
|
||||
const params: Record<string, any> = {
|
||||
instanceId: this.viewInstanceId,
|
||||
userAgentOverride: this.userAgentOverride
|
||||
instanceId: this.viewInstanceId
|
||||
};
|
||||
|
||||
for (const [attributeName, attribute] of this.attributes) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "18.0.0-nightly.20220107",
|
||||
"version": "19.0.0-nightly.20220310",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
@@ -33,7 +33,7 @@
|
||||
"asar": "^3.1.0",
|
||||
"aws-sdk": "^2.814.0",
|
||||
"check-for-leaks": "^1.2.1",
|
||||
"colors": "^1.4.0",
|
||||
"colors": "1.4.0",
|
||||
"dotenv-safe": "^4.0.4",
|
||||
"dugite": "^1.103.0",
|
||||
"eslint": "^7.4.0",
|
||||
@@ -67,7 +67,7 @@
|
||||
"timers-browserify": "1.4.2",
|
||||
"ts-loader": "^8.0.2",
|
||||
"ts-node": "6.2.0",
|
||||
"typescript": "^4.1.3",
|
||||
"typescript": "^4.5.5",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"wrapper-webpack-plugin": "^2.1.0"
|
||||
|
||||
@@ -2,3 +2,4 @@ expose_ripemd160.patch
|
||||
expose_aes-cfb.patch
|
||||
expose_des-ede3.patch
|
||||
fix_sync_evp_get_cipherbynid_and_evp_get_cipherbyname.patch
|
||||
expose_blowfish_ciphers.patch
|
||||
|
||||
@@ -58,10 +58,10 @@ index 852b76bea69988e0b3ac76a17b603128f239dde0..d443f4dc2daea0b7aa86ae75d31d995f
|
||||
callback(EVP_aes_192_ctr(), "aes-192-ctr", NULL, arg);
|
||||
callback(EVP_aes_256_ctr(), "aes-256-ctr", NULL, arg);
|
||||
diff --git a/include/openssl/cipher.h b/include/openssl/cipher.h
|
||||
index 09d72ec2c343f23409d35eca804a02e3290c86f1..1bea1a88b265312d700729ad2828f0b5d9f2d84f 100644
|
||||
index 2458847e5640fe955a9971aa77c27251e5091db5..a0b3ac5f6b55921a542f27108beca93d6372c6fc 100644
|
||||
--- a/include/openssl/cipher.h
|
||||
+++ b/include/openssl/cipher.h
|
||||
@@ -436,6 +436,7 @@ OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_ecb(void);
|
||||
@@ -448,6 +448,7 @@ OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_ecb(void);
|
||||
|
||||
// EVP_aes_128_cfb128 is only available in decrepit.
|
||||
OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_cfb128(void);
|
||||
|
||||
47
patches/boringssl/expose_blowfish_ciphers.patch
Normal file
47
patches/boringssl/expose_blowfish_ciphers.patch
Normal file
@@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Rose <nornagon@nornagon.net>
|
||||
Date: Wed, 5 Jan 2022 13:08:10 -0800
|
||||
Subject: expose blowfish ciphers
|
||||
|
||||
This exposes the (decrepit) blowfish cipher family, bf-cbc, bf-cfb and
|
||||
bf-ecb through the EVP interface. This adds references to decrepit code
|
||||
from non-decrepit code, so upstream is unlikely to take the patch.
|
||||
|
||||
diff --git a/crypto/cipher_extra/cipher_extra.c b/crypto/cipher_extra/cipher_extra.c
|
||||
index cfdb69e3c556fea11aa7c2d28d4b7da524df15c3..95bd172c99874610ec9157c52df4fe0232e78c7f 100644
|
||||
--- a/crypto/cipher_extra/cipher_extra.c
|
||||
+++ b/crypto/cipher_extra/cipher_extra.c
|
||||
@@ -89,6 +89,9 @@ static const struct {
|
||||
{NID_aes_256_ecb, "aes-256-ecb", EVP_aes_256_ecb},
|
||||
{NID_aes_256_gcm, "aes-256-gcm", EVP_aes_256_gcm},
|
||||
{NID_aes_256_ofb128, "aes-256-ofb", EVP_aes_256_ofb},
|
||||
+ {NID_bf_cbc, "bf-cbc", EVP_bf_cbc},
|
||||
+ {NID_bf_cfb64, "bf-cfb", EVP_bf_cfb},
|
||||
+ {NID_bf_ecb, "bf-ecb", EVP_bf_ecb},
|
||||
{NID_des_cbc, "des-cbc", EVP_des_cbc},
|
||||
{NID_des_ecb, "des-ecb", EVP_des_ecb},
|
||||
{NID_des_ede_cbc, "des-ede-cbc", EVP_des_ede_cbc},
|
||||
diff --git a/decrepit/evp/evp_do_all.c b/decrepit/evp/evp_do_all.c
|
||||
index 5e71420b765019edea82a33884ace539cd91bda5..43fc792697519325725e9ce87801c5dc176c70a1 100644
|
||||
--- a/decrepit/evp/evp_do_all.c
|
||||
+++ b/decrepit/evp/evp_do_all.c
|
||||
@@ -36,6 +36,9 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
|
||||
callback(EVP_aes_128_gcm(), "AES-128-GCM", NULL, arg);
|
||||
callback(EVP_aes_192_gcm(), "AES-192-GCM", NULL, arg);
|
||||
callback(EVP_aes_256_gcm(), "AES-256-GCM", NULL, arg);
|
||||
+ callback(EVP_bf_cbc(), "BF-CBC", NULL, arg);
|
||||
+ callback(EVP_bf_cfb(), "BF-CFB", NULL, arg);
|
||||
+ callback(EVP_bf_ecb(), "BF-ECB", NULL, arg);
|
||||
callback(EVP_des_cbc(), "DES-CBC", NULL, arg);
|
||||
callback(EVP_des_ecb(), "DES-ECB", NULL, arg);
|
||||
callback(EVP_des_ede(), "DES-EDE", NULL, arg);
|
||||
@@ -63,6 +66,9 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
|
||||
callback(EVP_aes_128_gcm(), "aes-128-gcm", NULL, arg);
|
||||
callback(EVP_aes_192_gcm(), "aes-192-gcm", NULL, arg);
|
||||
callback(EVP_aes_256_gcm(), "aes-256-gcm", NULL, arg);
|
||||
+ callback(EVP_bf_cbc(), "bf-cbc", NULL, arg);
|
||||
+ callback(EVP_bf_cfb(), "bf-cfb", NULL, arg);
|
||||
+ callback(EVP_bf_ecb(), "bf-ecb", NULL, arg);
|
||||
callback(EVP_des_cbc(), "des-cbc", NULL, arg);
|
||||
callback(EVP_des_ecb(), "des-ecb", NULL, arg);
|
||||
callback(EVP_des_ede(), "des-ede", NULL, arg);
|
||||
@@ -82,7 +82,7 @@ index a3fb077b9b9e66d1bc524fd7987622e73aa4776a..852b76bea69988e0b3ac76a17b603128
|
||||
|
||||
void EVP_MD_do_all(void (*callback)(const EVP_MD *cipher, const char *name,
|
||||
diff --git a/include/openssl/digest.h b/include/openssl/digest.h
|
||||
index fa7616896b6cc7422dc0171db29316f20fb25de8..6c19a0f0d454bef1abf16ebfeef380a53fb21e5c 100644
|
||||
index 6e889993edc1caa7e10670529dd270c337b5ae4c..f61f7e5009a9b4f5630cda2c3a5a21b44e5b88d8 100644
|
||||
--- a/include/openssl/digest.h
|
||||
+++ b/include/openssl/digest.h
|
||||
@@ -90,6 +90,9 @@ OPENSSL_EXPORT const EVP_MD *EVP_blake2b256(void);
|
||||
|
||||
@@ -48,7 +48,6 @@ worker_context_will_destroy.patch
|
||||
frame_host_manager.patch
|
||||
crashpad_pid_check.patch
|
||||
network_service_allow_remote_certificate_verification_logic.patch
|
||||
put_back_deleted_colors_for_autofill.patch
|
||||
disable_color_correct_rendering.patch
|
||||
add_contentgpuclient_precreatemessageloop_callback.patch
|
||||
picture-in-picture.patch
|
||||
@@ -64,7 +63,6 @@ allow_disabling_blink_scheduler_throttling_per_renderview.patch
|
||||
hack_plugin_response_interceptor_to_point_to_electron.patch
|
||||
feat_add_support_for_overriding_the_base_spellchecker_download_url.patch
|
||||
feat_enable_offscreen_rendering_with_viz_compositor.patch
|
||||
delay_lock_the_protocol_scheme_registry.patch
|
||||
gpu_notify_when_dxdiag_request_fails.patch
|
||||
feat_allow_embedders_to_add_observers_on_created_hunspell.patch
|
||||
feat_add_onclose_to_messageport.patch
|
||||
@@ -93,7 +91,6 @@ webview_fullscreen.patch
|
||||
disable_unload_metrics.patch
|
||||
fix_add_check_for_sandbox_then_result.patch
|
||||
extend_apply_webpreferences.patch
|
||||
make_include_of_stack_trace_h_unconditional.patch
|
||||
build_libc_as_static_library.patch
|
||||
build_do_not_depend_on_packed_resource_integrity.patch
|
||||
refactor_restore_base_adaptcallbackforrepeating.patch
|
||||
@@ -106,8 +103,14 @@ chore_do_not_use_chrome_windows_in_cryptotoken_webrequestsender.patch
|
||||
process_singleton.patch
|
||||
fix_expose_decrementcapturercount_in_web_contents_impl.patch
|
||||
add_ui_scopedcliboardwriter_writeunsaferawdata.patch
|
||||
feat_add_data_parameter_to_processsingleton.patch
|
||||
mas_gate_private_enterprise_APIs.patch
|
||||
load_v8_snapshot_in_browser_process.patch
|
||||
fix_patch_out_permissions_checks_in_exclusive_access.patch
|
||||
fix_aspect_ratio_with_max_size.patch
|
||||
fix_dont_delete_SerialPortManager_on_main_thread.patch
|
||||
feat_add_data_transfer_to_requestsingleinstancelock.patch
|
||||
fix_crash_when_saving_edited_pdf_files.patch
|
||||
port_autofill_colors_to_the_color_pipeline.patch
|
||||
build_disable_partition_alloc_on_mac.patch
|
||||
build_disable_thin_lto_on_mac.patch
|
||||
fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch
|
||||
|
||||
@@ -10,7 +10,7 @@ This patch makes three changes to Accelerator::GetShortcutText to improve shortc
|
||||
3. Ctrl-Shift-= and Ctrl-Plus show up as such
|
||||
|
||||
diff --git a/ui/base/accelerators/accelerator.cc b/ui/base/accelerators/accelerator.cc
|
||||
index be0df3662e3a1528fb88d5c723da49e5a29ac2b9..64a5eda05be16b3b6e1a0ceaa2b3a6884ca37268 100644
|
||||
index 2468b2c5881821d6f8e24a0e7c42243427b384ad..7e44c97edabf5ae012ff4f84d1404d8f223a13fe 100644
|
||||
--- a/ui/base/accelerators/accelerator.cc
|
||||
+++ b/ui/base/accelerators/accelerator.cc
|
||||
@@ -11,6 +11,7 @@
|
||||
@@ -30,7 +30,7 @@ index be0df3662e3a1528fb88d5c723da49e5a29ac2b9..64a5eda05be16b3b6e1a0ceaa2b3a688
|
||||
+ if (shifted_char) {
|
||||
+ shortcut += *shifted_char;
|
||||
+ } else {
|
||||
#if defined(OS_WIN)
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// Our fallback is to try translate the key code to a regular character
|
||||
// unless it is one of digits (VK_0 to VK_9). Some keyboard
|
||||
@@ -261,6 +267,10 @@ std::u16string Accelerator::GetShortcutText() const {
|
||||
@@ -43,7 +43,7 @@ index be0df3662e3a1528fb88d5c723da49e5a29ac2b9..64a5eda05be16b3b6e1a0ceaa2b3a688
|
||||
+ base::StringPrintf("F%d", key_code_ - VKEY_F1 + 1));
|
||||
}
|
||||
|
||||
#if defined(OS_MAC)
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
@@ -451,7 +461,7 @@ std::u16string Accelerator::ApplyLongFormModifiers(
|
||||
const std::u16string& shortcut) const {
|
||||
std::u16string result = shortcut;
|
||||
@@ -63,7 +63,7 @@ index be0df3662e3a1528fb88d5c723da49e5a29ac2b9..64a5eda05be16b3b6e1a0ceaa2b3a688
|
||||
|
||||
if (IsCmdDown()) {
|
||||
diff --git a/ui/base/accelerators/accelerator.h b/ui/base/accelerators/accelerator.h
|
||||
index 5cdb2f160beae4d7787eb84d5013280ee9464446..76bd4369faa5d43d8a99ea51ed012857d6bff293 100644
|
||||
index e0d9df439d120c0a47f55666b3818c7ba6796e70..283c6283f5aeaae1a5436e5fbb17ce2db4a9034e 100644
|
||||
--- a/ui/base/accelerators/accelerator.h
|
||||
+++ b/ui/base/accelerators/accelerator.h
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
@@ -10,10 +10,10 @@ Allows Electron to restore WER when ELECTRON_DEFAULT_ERROR_MODE is set.
|
||||
This should be upstreamed.
|
||||
|
||||
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
|
||||
index a28a1fe24ac95191fa2f88d7df388b6ea7885d57..988ab894b756147ddae072c4d11c5d8d07b46563 100644
|
||||
index 9f840287967b50ec1db3a9d27973429ab231a486..731a279e395a8762a25a115665bff99be428de3d 100644
|
||||
--- a/content/gpu/gpu_main.cc
|
||||
+++ b/content/gpu/gpu_main.cc
|
||||
@@ -236,6 +236,10 @@ int GpuMain(MainFunctionParams parameters) {
|
||||
@@ -239,6 +239,10 @@ int GpuMain(MainFunctionParams parameters) {
|
||||
// to the GpuProcessHost once the GpuServiceImpl has started.
|
||||
viz::GpuServiceImpl::InstallPreInitializeLogHandler();
|
||||
|
||||
@@ -24,7 +24,7 @@ index a28a1fe24ac95191fa2f88d7df388b6ea7885d57..988ab894b756147ddae072c4d11c5d8d
|
||||
// We are experiencing what appear to be memory-stomp issues in the GPU
|
||||
// process. These issues seem to be impacting the task executor and listeners
|
||||
// registered to it. Create the task executor on the heap to guard against
|
||||
@@ -342,7 +346,6 @@ int GpuMain(MainFunctionParams parameters) {
|
||||
@@ -345,7 +349,6 @@ int GpuMain(MainFunctionParams parameters) {
|
||||
GpuProcess gpu_process(io_thread_priority);
|
||||
#endif
|
||||
|
||||
@@ -33,10 +33,10 @@ index a28a1fe24ac95191fa2f88d7df388b6ea7885d57..988ab894b756147ddae072c4d11c5d8d
|
||||
client->PostIOThreadCreated(gpu_process.io_task_runner());
|
||||
|
||||
diff --git a/content/public/gpu/content_gpu_client.h b/content/public/gpu/content_gpu_client.h
|
||||
index cb7774f89cb0a5537630208dc784c63a4b5a6f34..9baf51f1c5bfcd809d3bba47f96c2772158a51ac 100644
|
||||
index 04274b751b498456fc4b269bfbc6399b4f27d3ed..2fb98baf0df4e191e5e18fd7055cc2d92a2156df 100644
|
||||
--- a/content/public/gpu/content_gpu_client.h
|
||||
+++ b/content/public/gpu/content_gpu_client.h
|
||||
@@ -28,6 +28,10 @@ class CONTENT_EXPORT ContentGpuClient {
|
||||
@@ -29,6 +29,10 @@ class CONTENT_EXPORT ContentGpuClient {
|
||||
public:
|
||||
virtual ~ContentGpuClient() {}
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ DidCreateScriptContext is called, not all JS APIs are available in the
|
||||
context, which can cause some preload scripts to trip.
|
||||
|
||||
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h
|
||||
index 316b6730c255e5fafb7fb86ee4f780a28368d771..9601b3b9c5d5da9c9051aa234d2eaa932ef983ee 100644
|
||||
index a92e09dc651a5f1a9bbae2572fad32233afcd46c..f99b652dda817b62615d2b3f00b4ae4b438ec44d 100644
|
||||
--- a/content/public/renderer/render_frame_observer.h
|
||||
+++ b/content/public/renderer/render_frame_observer.h
|
||||
@@ -130,6 +130,8 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
|
||||
@@ -129,6 +129,8 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
|
||||
virtual void DidHandleOnloadEvents() {}
|
||||
virtual void DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
int32_t world_id) {}
|
||||
@@ -23,10 +23,10 @@ index 316b6730c255e5fafb7fb86ee4f780a28368d771..9601b3b9c5d5da9c9051aa234d2eaa93
|
||||
int32_t world_id) {}
|
||||
virtual void DidClearWindowObject() {}
|
||||
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
|
||||
index 454b8a57e6654a07c5ba4798c21a2792730a4de5..b517bd4337fcda3b167388962657344388f0b74d 100644
|
||||
index 4473c5e812a4a598f3e2f2bb06f78def5791af24..44c0ec9815aafd61182fd18a9d125e185d7196bc 100644
|
||||
--- a/content/renderer/render_frame_impl.cc
|
||||
+++ b/content/renderer/render_frame_impl.cc
|
||||
@@ -4499,6 +4499,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
@@ -4455,6 +4455,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
observer.DidCreateScriptContext(context, world_id);
|
||||
}
|
||||
|
||||
@@ -40,10 +40,10 @@ index 454b8a57e6654a07c5ba4798c21a2792730a4de5..b517bd4337fcda3b1673889626573443
|
||||
int world_id) {
|
||||
for (auto& observer : observers_)
|
||||
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
|
||||
index ed716709fbee0e81af2f9ad19c7bcce021c65926..ee3d1865aebc2c11400e72534322818319ee900d 100644
|
||||
index 21b90bbb8fe8ddc03eb20538be423a5396d18eb3..f9c735038f733d990783dd66ffe8c74f824c78f2 100644
|
||||
--- a/content/renderer/render_frame_impl.h
|
||||
+++ b/content/renderer/render_frame_impl.h
|
||||
@@ -600,6 +600,8 @@ class CONTENT_EXPORT RenderFrameImpl
|
||||
@@ -597,6 +597,8 @@ class CONTENT_EXPORT RenderFrameImpl
|
||||
blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) override;
|
||||
void DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
int world_id) override;
|
||||
@@ -53,10 +53,10 @@ index ed716709fbee0e81af2f9ad19c7bcce021c65926..ee3d1865aebc2c11400e725343228183
|
||||
int world_id) override;
|
||||
void DidChangeScrollOffset() override;
|
||||
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
|
||||
index 994841c02b0472e5239d9b73a07b2592a39df8be..ad19a3cddf200f6600a04c1136fd21218d496ba8 100644
|
||||
index 3d6e0c0395ff7c92d8908c5151b467beec3a7516..2fadd6d9b2e3747eacea08973d8d3c7aa9c15f26 100644
|
||||
--- a/third_party/blink/public/web/web_local_frame_client.h
|
||||
+++ b/third_party/blink/public/web/web_local_frame_client.h
|
||||
@@ -596,6 +596,9 @@ class BLINK_EXPORT WebLocalFrameClient {
|
||||
@@ -599,6 +599,9 @@ class BLINK_EXPORT WebLocalFrameClient {
|
||||
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) {}
|
||||
|
||||
@@ -67,10 +67,10 @@ index 994841c02b0472e5239d9b73a07b2592a39df8be..ad19a3cddf200f6600a04c1136fd2121
|
||||
virtual void WillReleaseScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) {}
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
|
||||
index c53d1af1946d9caefc3682c5caff3b6ccb2a0804..91b908d884d65767b9fc54e6711590edff952bcd 100644
|
||||
index aa4b510137d60e6fb924f4f1a6554fe06c19ad75..816b6260020a6cbb6880b0eed197743ccd9002f5 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
|
||||
@@ -213,6 +213,7 @@ void LocalWindowProxy::Initialize() {
|
||||
@@ -205,6 +205,7 @@ void LocalWindowProxy::Initialize() {
|
||||
}
|
||||
|
||||
InstallConditionalFeatures();
|
||||
@@ -79,10 +79,10 @@ index c53d1af1946d9caefc3682c5caff3b6ccb2a0804..91b908d884d65767b9fc54e6711590ed
|
||||
if (World().IsMainWorld()) {
|
||||
GetFrame()->Loader().DispatchDidClearWindowObjectInMainWorld();
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
index c28bc5f4d285ab2db1b0501ad8663c4f948f3ddc..327c04b40460fc033ca7f4e4f838608cfc6c0ba3 100644
|
||||
index 0dda1f7cd77c47f7e61ba48dd20429c13679b543..2f73aacda1bafe07775213e232eda56c4b33325b 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
@@ -311,6 +311,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
|
||||
@@ -308,6 +308,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
|
||||
|
||||
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) = 0;
|
||||
@@ -92,7 +92,7 @@ index c28bc5f4d285ab2db1b0501ad8663c4f948f3ddc..327c04b40460fc033ca7f4e4f838608c
|
||||
int32_t world_id) = 0;
|
||||
virtual bool AllowScriptExtensions() = 0;
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
|
||||
index a07cd4deeb88c768f27844feafaaa56b2f0e2692..aef718592fdf298493e8e52950f0858a8666bd1c 100644
|
||||
index 5297ad63f1c76240d57a64cc5ea64cbf8c7e1b95..006da6072db12da1632f9d45ecb5710136573641 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
|
||||
@@ -274,6 +274,13 @@ void LocalFrameClientImpl::DidCreateScriptContext(
|
||||
@@ -110,7 +110,7 @@ index a07cd4deeb88c768f27844feafaaa56b2f0e2692..aef718592fdf298493e8e52950f0858a
|
||||
v8::Local<v8::Context> context,
|
||||
int32_t world_id) {
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
|
||||
index 5c89861a1e3e37b3b54d73e4b6ec1c2b34c491b2..a566fc7156c8440c5a3337103db4120b62fff5dd 100644
|
||||
index 708414fca139eb8328e425d909a48ca97038e442..48b2a0e129ec166ebd4c9bbd32330b0cc43dbeb2 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
|
||||
@@ -78,6 +78,8 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
|
||||
@@ -123,10 +123,10 @@ index 5c89861a1e3e37b3b54d73e4b6ec1c2b34c491b2..a566fc7156c8440c5a3337103db4120b
|
||||
int32_t world_id) override;
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
index 9ec5c2d4be13572e4060c03a822cb792329e1c94..b9c8c4f3b7d4c98cf6411c4bbb9ef96f3db55328 100644
|
||||
index 4b639069d5d9173f0c35fe7656356031ba424a61..3da6699b40bf4f91e6d76a37e5fa8f680f7a7850 100644
|
||||
--- a/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
@@ -356,6 +356,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
|
||||
@@ -357,6 +357,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
|
||||
|
||||
void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) override {}
|
||||
|
||||
@@ -8,12 +8,12 @@ was removed as part of the Raw Clipboard API scrubbing.
|
||||
https://bugs.chromium.org/p/chromium/issues/detail?id=1217643
|
||||
|
||||
diff --git a/ui/base/clipboard/scoped_clipboard_writer.cc b/ui/base/clipboard/scoped_clipboard_writer.cc
|
||||
index 153f169d2cdef6f8a726c188283a5bc1b7395fa3..3a5d9ab8dafacafb1025e1cb8c157e8a82078424 100644
|
||||
index 3009acd40eee36bc3d4dd8642f0ce5e6476da973..1d52ce84184a3ca94e4e0f04d331bf56d75e07d0 100644
|
||||
--- a/ui/base/clipboard/scoped_clipboard_writer.cc
|
||||
+++ b/ui/base/clipboard/scoped_clipboard_writer.cc
|
||||
@@ -212,6 +212,16 @@ void ScopedClipboardWriter::WriteData(const std::u16string& format,
|
||||
}
|
||||
@@ -227,6 +227,16 @@ void ScopedClipboardWriter::WriteEncodedDataTransferEndpointForTesting(
|
||||
}
|
||||
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
|
||||
+void ScopedClipboardWriter::WriteUnsafeRawData(const std::u16string& format,
|
||||
+ mojo_base::BigBuffer data) {
|
||||
@@ -29,10 +29,10 @@ index 153f169d2cdef6f8a726c188283a5bc1b7395fa3..3a5d9ab8dafacafb1025e1cb8c157e8a
|
||||
objects_.clear();
|
||||
platform_representations_.clear();
|
||||
diff --git a/ui/base/clipboard/scoped_clipboard_writer.h b/ui/base/clipboard/scoped_clipboard_writer.h
|
||||
index 879acd4f6f0101a6da3af58d78eeda877ea41a4a..4d4149b6aa34c7073804994cb1c03368830c736d 100644
|
||||
index c47909313da0d7cd8a2b3cd670327011af66e3fb..0d259c21507f38124dfa46aceeacfda76cfd4a38 100644
|
||||
--- a/ui/base/clipboard/scoped_clipboard_writer.h
|
||||
+++ b/ui/base/clipboard/scoped_clipboard_writer.h
|
||||
@@ -80,6 +80,10 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter {
|
||||
@@ -84,6 +84,10 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter {
|
||||
// This is only used to write custom format data.
|
||||
void WriteData(const std::u16string& format, mojo_base::BigBuffer data);
|
||||
|
||||
@@ -42,4 +42,4 @@ index 879acd4f6f0101a6da3af58d78eeda877ea41a4a..4d4149b6aa34c7073804994cb1c03368
|
||||
+
|
||||
void WriteImage(const SkBitmap& bitmap);
|
||||
|
||||
// Mark the data to be written as confidential.
|
||||
#if BUILDFLAG(IS_CHROMEOS_LACROS)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user