mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
467 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dee6e01e9e | ||
|
|
483e39cc74 | ||
|
|
cd7490d233 | ||
|
|
b990bd6c97 | ||
|
|
56a0b45ef2 | ||
|
|
5871f81bb9 | ||
|
|
511f27506f | ||
|
|
8189ee64b9 | ||
|
|
cc52f07023 | ||
|
|
890adefb95 | ||
|
|
348e76b1d6 | ||
|
|
cfee3286b2 | ||
|
|
d7acbeb8ee | ||
|
|
b35c90777a | ||
|
|
b5bc30da45 | ||
|
|
3ca4944ad8 | ||
|
|
40fcfaa5e9 | ||
|
|
da6e16157f | ||
|
|
358d6f83cf | ||
|
|
c5918acbf1 | ||
|
|
dba8e7fe42 | ||
|
|
2fc331859f | ||
|
|
c3a3274826 | ||
|
|
675737397d | ||
|
|
5059502456 | ||
|
|
b1093f454c | ||
|
|
51146df170 | ||
|
|
1c59c8eb61 | ||
|
|
09bb0c14a7 | ||
|
|
fcef0963d2 | ||
|
|
b608874076 | ||
|
|
f06842e6f8 | ||
|
|
4119881a36 | ||
|
|
ecb9afd7d6 | ||
|
|
a70431f8db | ||
|
|
b21dae6bee | ||
|
|
cb3fef890f | ||
|
|
b61a6f8021 | ||
|
|
b390336a5c | ||
|
|
7a9747021d | ||
|
|
18fd51af5f | ||
|
|
9e51cf4a65 | ||
|
|
76a07c227d | ||
|
|
9308ac6e67 | ||
|
|
3823245a46 | ||
|
|
f49f74831b | ||
|
|
0b26e76739 | ||
|
|
079010f01a | ||
|
|
8f673fe81d | ||
|
|
1012fd687a | ||
|
|
871be236f8 | ||
|
|
cee4a64493 | ||
|
|
d71c08a404 | ||
|
|
5a0f75f42c | ||
|
|
f5e26258da | ||
|
|
6165f6afc9 | ||
|
|
35f871c702 | ||
|
|
8c3c382673 | ||
|
|
16ae9e16cf | ||
|
|
1d14d15d8c | ||
|
|
32df7f58bb | ||
|
|
66c3319458 | ||
|
|
49955512a8 | ||
|
|
977dc2527e | ||
|
|
4f70332460 | ||
|
|
d8e1f4f73b | ||
|
|
ec40581e83 | ||
|
|
22cdcf400c | ||
|
|
1b36d1d175 | ||
|
|
4578597dea | ||
|
|
20deb65058 | ||
|
|
7b7d22fa7c | ||
|
|
851350b9f3 | ||
|
|
7162f641b5 | ||
|
|
88e3f4a1e6 | ||
|
|
0d1900048d | ||
|
|
af65324717 | ||
|
|
6d1cc18322 | ||
|
|
4d73469ed5 | ||
|
|
ca17f574de | ||
|
|
a5fdd272b1 | ||
|
|
15f3c45fe9 | ||
|
|
3f01fb3110 | ||
|
|
96789ee78b | ||
|
|
4b8885ffc8 | ||
|
|
c47b196d02 | ||
|
|
d67c319642 | ||
|
|
6839dd92b8 | ||
|
|
d468a73edb | ||
|
|
e4dbd1407e | ||
|
|
37a422d05b | ||
|
|
26e7f27110 | ||
|
|
707e8d5b7b | ||
|
|
6fda94858d | ||
|
|
1eece7ada0 | ||
|
|
c33bfffeec | ||
|
|
02bf71fb43 | ||
|
|
74b85afca4 | ||
|
|
fbc398f9bc | ||
|
|
4c32d141d8 | ||
|
|
88bedfcf25 | ||
|
|
f4ba63536a | ||
|
|
f024af603c | ||
|
|
9c669210c4 | ||
|
|
1bd99405ad | ||
|
|
ef939db944 | ||
|
|
e7e8b324ff | ||
|
|
b4533d19e6 | ||
|
|
2ecc68621f | ||
|
|
0971add78a | ||
|
|
ebd134881b | ||
|
|
448069cd04 | ||
|
|
7afc5ab88e | ||
|
|
601ca745c1 | ||
|
|
ba3a6c1193 | ||
|
|
af3e3ff0cb | ||
|
|
85e19bd0ad | ||
|
|
cc428fdea2 | ||
|
|
553573e6ff | ||
|
|
f057e0669d | ||
|
|
4ae399e4eb | ||
|
|
418c957e13 | ||
|
|
fe96879a9d | ||
|
|
8acf68c980 | ||
|
|
11a0e2a402 | ||
|
|
fabdfb2c18 | ||
|
|
eca4b1325f | ||
|
|
3bc25c997d | ||
|
|
b715e8714a | ||
|
|
2a0828e69a | ||
|
|
5d46db1839 | ||
|
|
9d482f438a | ||
|
|
7630fc801e | ||
|
|
6b2375cba0 | ||
|
|
c017200e85 | ||
|
|
daf55a81b1 | ||
|
|
067314ec32 | ||
|
|
a128449e3d | ||
|
|
de74dce663 | ||
|
|
0e3a558913 | ||
|
|
e2d4a98c76 | ||
|
|
015e9a8843 | ||
|
|
1fc8f72126 | ||
|
|
6a91276172 | ||
|
|
32ab3297fa | ||
|
|
3b4e17e7e2 | ||
|
|
6c314dc08b | ||
|
|
cd6a17db08 | ||
|
|
b6d6f86ee8 | ||
|
|
178688fe61 | ||
|
|
40f6e2ee7e | ||
|
|
f747f071fb | ||
|
|
8476bfbcaa | ||
|
|
d1abb62943 | ||
|
|
86bf9ea252 | ||
|
|
ffb8749243 | ||
|
|
feea88600a | ||
|
|
89188cd4e9 | ||
|
|
45c1d22489 | ||
|
|
3f39d85501 | ||
|
|
2dd7749181 | ||
|
|
5634ddc665 | ||
|
|
6de6d3966a | ||
|
|
02562e903b | ||
|
|
718ef5269f | ||
|
|
ddaa4a9686 | ||
|
|
f646744d32 | ||
|
|
75ccd1fb65 | ||
|
|
f30034d1a9 | ||
|
|
00b6524793 | ||
|
|
f8f08814a2 | ||
|
|
0a758c418c | ||
|
|
daff2057a4 | ||
|
|
67f2f9e024 | ||
|
|
3ee1a45d76 | ||
|
|
652d87282a | ||
|
|
923788b4e4 | ||
|
|
541504c8a4 | ||
|
|
490584834e | ||
|
|
a269ebd1d8 | ||
|
|
0f073186ff | ||
|
|
73e216f182 | ||
|
|
0a80eb4a9c | ||
|
|
50e386ead4 | ||
|
|
5f0810a177 | ||
|
|
65f3729bfb | ||
|
|
b5bdd26a45 | ||
|
|
9ac2ee317d | ||
|
|
a600027384 | ||
|
|
7f82836d67 | ||
|
|
769088f8dc | ||
|
|
c85bc3c932 | ||
|
|
3cd795a927 | ||
|
|
6179b03fa1 | ||
|
|
72c48aa400 | ||
|
|
befe53e5ad | ||
|
|
41aaed307d | ||
|
|
0d17fac455 | ||
|
|
5c3d6aaa81 | ||
|
|
da6996dc63 | ||
|
|
4cfa648a2e | ||
|
|
86294aa1d0 | ||
|
|
50d9fd215e | ||
|
|
06b3615e30 | ||
|
|
8680415128 | ||
|
|
35bf159cd3 | ||
|
|
f8c7408279 | ||
|
|
9b1e7a8963 | ||
|
|
765e1025f4 | ||
|
|
a5d2a56105 | ||
|
|
d8f43ed7bd | ||
|
|
f1b30c26f9 | ||
|
|
c80f701085 | ||
|
|
fa6dde3e1c | ||
|
|
bb6a072380 | ||
|
|
743e442796 | ||
|
|
4abb7e9709 | ||
|
|
8b996a478a | ||
|
|
d36dc1c7de | ||
|
|
e5c56c08a4 | ||
|
|
1763f4cfc8 | ||
|
|
700887d623 | ||
|
|
f893707c5d | ||
|
|
dcf825bed6 | ||
|
|
cee4e3707f | ||
|
|
e9fa834757 | ||
|
|
a327684118 | ||
|
|
ef5424cee0 | ||
|
|
388acd7e2a | ||
|
|
46d74390fc | ||
|
|
d305082ab7 | ||
|
|
0370583c73 | ||
|
|
91274e5a7e | ||
|
|
fc3172dd2a | ||
|
|
7e0b787a76 | ||
|
|
4556adde82 | ||
|
|
7283c257ae | ||
|
|
bf5a0cdd6a | ||
|
|
1c8e9b3651 | ||
|
|
90726a46e1 | ||
|
|
9cd76a8e52 | ||
|
|
a9b17793de | ||
|
|
134042cc43 | ||
|
|
26d729a4a3 | ||
|
|
68c3c3f7ad | ||
|
|
92cd3d1fa5 | ||
|
|
47f8a13384 | ||
|
|
19c3e1c8b7 | ||
|
|
7e771a3db5 | ||
|
|
c5ec2099bb | ||
|
|
262cc48ad0 | ||
|
|
fb5741efd6 | ||
|
|
47669c55fd | ||
|
|
7b76a70e07 | ||
|
|
b4466f8f3e | ||
|
|
2e9ccd4372 | ||
|
|
1528b0d307 | ||
|
|
da86676a43 | ||
|
|
0579822008 | ||
|
|
ff64cd722f | ||
|
|
fea2aabdd4 | ||
|
|
3bbbf4b27f | ||
|
|
6dc7384f3a | ||
|
|
68c541380e | ||
|
|
fe8c831a0c | ||
|
|
cc9ba35c51 | ||
|
|
56ccfad7a5 | ||
|
|
47bda9c0e5 | ||
|
|
4f27c367b1 | ||
|
|
339ae4c014 | ||
|
|
c1f4b6a4cb | ||
|
|
0a908224c2 | ||
|
|
34c4889bbb | ||
|
|
8c066c2a35 | ||
|
|
7c9b609389 | ||
|
|
7ab85558f5 | ||
|
|
ca06034fdd | ||
|
|
d07fe4480f | ||
|
|
c2195915d8 | ||
|
|
57408e4c2a | ||
|
|
0012e01c86 | ||
|
|
2b97ff3fba | ||
|
|
87590da2fb | ||
|
|
493751b321 | ||
|
|
36008e0dea | ||
|
|
2871698148 | ||
|
|
9d8dde5c76 | ||
|
|
f72efecf95 | ||
|
|
5b45cb3f77 | ||
|
|
ad2b136425 | ||
|
|
94f4c18d7c | ||
|
|
f7f41fee99 | ||
|
|
907e9c8c0e | ||
|
|
4d2968bfc1 | ||
|
|
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 | ||
|
|
948db1d881 | ||
|
|
824c909e2a | ||
|
|
7678a0aebb | ||
|
|
88ae6c0635 | ||
|
|
a015332342 | ||
|
|
5af6b898d9 | ||
|
|
d44a187d0b | ||
|
|
2f9fd06534 | ||
|
|
c3b9f0e7b2 | ||
|
|
c1c710bc01 | ||
|
|
30e0620ccc | ||
|
|
b61805b63a | ||
|
|
dd4eae8a3b | ||
|
|
62c1c86be9 | ||
|
|
b63c190fe6 | ||
|
|
cbdb2e6ec2 | ||
|
|
84f1d78558 | ||
|
|
4600d7e7f6 | ||
|
|
2c700da4de | ||
|
|
195d2b5b3e | ||
|
|
727453ef04 | ||
|
|
84451e7daf | ||
|
|
f766bb483d | ||
|
|
1d8612ad5d | ||
|
|
ac39cb14e9 | ||
|
|
f1b0d30d8d | ||
|
|
d59a4a0771 | ||
|
|
6b2adea867 | ||
|
|
66a55ba778 | ||
|
|
f17e8996ac | ||
|
|
b433163d7a | ||
|
|
79eaef4aab | ||
|
|
2b25e737a7 | ||
|
|
ffbaa1d83f | ||
|
|
909dbe6890 | ||
|
|
eaae6c1553 | ||
|
|
e9420982d2 | ||
|
|
c1b3b3064b | ||
|
|
a11f5cbb27 | ||
|
|
1facbb4a09 | ||
|
|
d5b6a2f800 | ||
|
|
292409a301 | ||
|
|
f887ca0082 | ||
|
|
6d9e2e3ad0 | ||
|
|
c4e471fbe2 | ||
|
|
1341b0a6b7 | ||
|
|
cf0959f834 | ||
|
|
f615075847 | ||
|
|
d53399ea31 | ||
|
|
df7eb209a5 | ||
|
|
12c5b9eaac | ||
|
|
35ac7fb8e6 | ||
|
|
77287febf4 | ||
|
|
f46e9c3205 | ||
|
|
f3df76dbdc | ||
|
|
0c5b01f5f6 | ||
|
|
eabfd6c1b9 | ||
|
|
cce427dc46 | ||
|
|
ed7f9ad5c2 | ||
|
|
bc8cfbac59 | ||
|
|
3d34fd7c91 | ||
|
|
ab92455fc8 | ||
|
|
90410e0419 | ||
|
|
83a4b234d7 | ||
|
|
3278ff6a05 | ||
|
|
395b43b293 | ||
|
|
43f36b5b24 | ||
|
|
46634bc0f2 | ||
|
|
24d272ca41 | ||
|
|
b4b0667d52 | ||
|
|
4609d4cb7a | ||
|
|
3834aaf4e9 | ||
|
|
f1b8f9692d | ||
|
|
b49a9629c0 | ||
|
|
e53f1af97e | ||
|
|
bd10b19b0c | ||
|
|
065cad6d2c | ||
|
|
9ab102e156 | ||
|
|
681fe435fe | ||
|
|
4713acce8d | ||
|
|
557e586667 | ||
|
|
c4ea33d1bf | ||
|
|
0865267387 | ||
|
|
239ba7d905 | ||
|
|
38d2ec0cb6 | ||
|
|
7ff15038d6 | ||
|
|
98a5996b30 | ||
|
|
eb56209206 | ||
|
|
0cb46a3712 | ||
|
|
3e71310a9f | ||
|
|
9f12edac65 |
1
.circleci/.gitignore
vendored
Normal file
1
.circleci/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
config-staging
|
||||
@@ -6,6 +6,7 @@ setup: true
|
||||
# Orbs
|
||||
orbs:
|
||||
path-filtering: circleci/path-filtering@0.1.0
|
||||
continuation: circleci/continuation@0.2.0
|
||||
|
||||
# All input parameters to pass to build config
|
||||
parameters:
|
||||
@@ -13,7 +14,7 @@ parameters:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
upload-to-s3:
|
||||
upload-to-storage:
|
||||
type: string
|
||||
default: '1'
|
||||
|
||||
@@ -43,103 +44,33 @@ parameters:
|
||||
default: all
|
||||
enum: ["all", "osx-x64", "osx-arm64", "mas-x64", "mas-arm64"]
|
||||
|
||||
# Envs
|
||||
env-global: &env-global
|
||||
ELECTRON_OUT_DIR: Default
|
||||
|
||||
env-linux-medium: &env-linux-medium
|
||||
<<: *env-global
|
||||
NUMBER_OF_NINJA_PROCESSES: 3
|
||||
|
||||
# Executors
|
||||
executors:
|
||||
linux-docker:
|
||||
parameters:
|
||||
size:
|
||||
description: "Docker executor size"
|
||||
default: 2xlarge+
|
||||
type: enum
|
||||
enum: ["medium", "xlarge", "2xlarge+"]
|
||||
docker:
|
||||
- image: ghcr.io/electron/build:27db4a3e3512bfd2e47f58cea69922da0835f1d9
|
||||
resource_class: << parameters.size >>
|
||||
|
||||
# List of always run steps
|
||||
step-checkout-electron: &step-checkout-electron
|
||||
checkout:
|
||||
path: src/electron
|
||||
|
||||
steps-lint: &steps-lint
|
||||
steps:
|
||||
- *step-checkout-electron
|
||||
- run:
|
||||
name: Setup third_party Depot Tools
|
||||
command: |
|
||||
# "depot_tools" has to be checkout into "//third_party/depot_tools" so pylint.py can a "pylintrc" file.
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git src/third_party/depot_tools
|
||||
echo 'export PATH="$PATH:'"$PWD"'/src/third_party/depot_tools"' >> $BASH_ENV
|
||||
- run:
|
||||
name: Download GN Binary
|
||||
command: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
gn_version="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)"
|
||||
|
||||
cipd ensure -ensure-file - -root . \<<-CIPD
|
||||
\$ServiceURL https://chrome-infra-packages.appspot.com/
|
||||
@Subdir src/buildtools/linux64
|
||||
gn/gn/linux-amd64 $gn_version
|
||||
CIPD
|
||||
|
||||
echo 'export CHROMIUM_BUILDTOOLS_PATH="'"$PWD"'/src/buildtools"' >> $BASH_ENV
|
||||
- run:
|
||||
name: Download clang-format Binary
|
||||
command: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
|
||||
sha1_path='buildtools/linux64/clang-format.sha1'
|
||||
curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/${sha1_path}?format=TEXT" | base64 -d > "src/${sha1_path}"
|
||||
|
||||
download_from_google_storage.py --no_resume --no_auth --bucket chromium-clang-format -s "src/${sha1_path}"
|
||||
- run:
|
||||
name: Run Lint
|
||||
command: |
|
||||
# gn.py tries to find a gclient root folder starting from the current dir.
|
||||
# When it fails and returns "None" path, the whole script fails. Let's "fix" it.
|
||||
touch .gclient
|
||||
# Another option would be to checkout "buildtools" inside the Electron checkout,
|
||||
# but then we would lint its contents (at least gn format), and it doesn't pass it.
|
||||
|
||||
cd src/electron
|
||||
node script/yarn install --frozen-lockfile
|
||||
node script/yarn lint
|
||||
- run:
|
||||
name: Run Script Typechecker
|
||||
command: |
|
||||
cd src/electron
|
||||
node script/yarn tsc -p tsconfig.script.json
|
||||
|
||||
# List of always run jobs.
|
||||
jobs:
|
||||
lint:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: medium
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *steps-lint
|
||||
|
||||
# Initial setup workflow
|
||||
workflows:
|
||||
lint:
|
||||
jobs:
|
||||
# Job inherited from path-filtering orb
|
||||
- path-filtering/filter:
|
||||
generate-config:
|
||||
docker:
|
||||
- image: cimg/node:16.14
|
||||
steps:
|
||||
- checkout
|
||||
- path-filtering/set-parameters:
|
||||
base-revision: main
|
||||
# Params for mapping; `path-to-test parameter-to-set value-for-parameter` for each row
|
||||
mapping: |
|
||||
^((?!docs/).)*$ run-build-mac true
|
||||
^((?!docs/).)*$ run-build-linux true
|
||||
docs/.* run-docs-only true
|
||||
^((?!docs/).)*$ run-docs-only false
|
||||
config-path: .circleci/build_config.yml
|
||||
- lint
|
||||
- run:
|
||||
command: |
|
||||
cd .circleci/config
|
||||
yarn
|
||||
export CIRCLECI_BINARY="$HOME/circleci"
|
||||
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | DESTDIR=$CIRCLECI_BINARY bash
|
||||
node build.js
|
||||
name: Pack config.yml
|
||||
- continuation/continue:
|
||||
configuration_path: .circleci/config-staging/built.yml
|
||||
parameters: /tmp/pipeline-parameters.json
|
||||
|
||||
# Initial setup workflow
|
||||
workflows:
|
||||
setup:
|
||||
jobs:
|
||||
- generate-config
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
34
.circleci/config/build.js
Normal file
34
.circleci/config/build.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const cp = require('child_process');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
const STAGING_DIR = path.resolve(__dirname, '..', 'config-staging');
|
||||
|
||||
function copyAndExpand(dir = './') {
|
||||
const absDir = path.resolve(__dirname, dir);
|
||||
const targetDir = path.resolve(STAGING_DIR, dir);
|
||||
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
fs.mkdirSync(targetDir);
|
||||
}
|
||||
|
||||
for (const file of fs.readdirSync(absDir)) {
|
||||
if (!file.endsWith('.yml')) {
|
||||
if (fs.statSync(path.resolve(absDir, file)).isDirectory()) {
|
||||
copyAndExpand(path.join(dir, file));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
fs.writeFileSync(path.resolve(targetDir, file), yaml.dump(yaml.load(fs.readFileSync(path.resolve(absDir, file), 'utf8')), {
|
||||
noRefs: true,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (fs.pathExists(STAGING_DIR)) fs.removeSync(STAGING_DIR);
|
||||
copyAndExpand();
|
||||
|
||||
const output = cp.spawnSync(process.env.CIRCLECI_BINARY || 'circleci', ['config', 'pack', STAGING_DIR]);
|
||||
fs.writeFileSync(path.resolve(STAGING_DIR, 'built.yml'), output.stdout.toString());
|
||||
51
.circleci/config/jobs/lint.yml
Normal file
51
.circleci/config/jobs/lint.yml
Normal file
@@ -0,0 +1,51 @@
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: medium
|
||||
steps:
|
||||
- checkout:
|
||||
path: src/electron
|
||||
- run:
|
||||
name: Setup third_party Depot Tools
|
||||
command: |
|
||||
# "depot_tools" has to be checkout into "//third_party/depot_tools" so pylint.py can a "pylintrc" file.
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git src/third_party/depot_tools
|
||||
echo 'export PATH="$PATH:'"$PWD"'/src/third_party/depot_tools"' >> $BASH_ENV
|
||||
- run:
|
||||
name: Download GN Binary
|
||||
command: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
gn_version="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)"
|
||||
|
||||
cipd ensure -ensure-file - -root . \<<-CIPD
|
||||
\$ServiceURL https://chrome-infra-packages.appspot.com/
|
||||
@Subdir src/buildtools/linux64
|
||||
gn/gn/linux-amd64 $gn_version
|
||||
CIPD
|
||||
|
||||
echo 'export CHROMIUM_BUILDTOOLS_PATH="'"$PWD"'/src/buildtools"' >> $BASH_ENV
|
||||
- run:
|
||||
name: Download clang-format Binary
|
||||
command: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
|
||||
sha1_path='buildtools/linux64/clang-format.sha1'
|
||||
curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/${sha1_path}?format=TEXT" | base64 -d > "src/${sha1_path}"
|
||||
|
||||
download_from_google_storage.py --no_resume --no_auth --bucket chromium-clang-format -s "src/${sha1_path}"
|
||||
- run:
|
||||
name: Run Lint
|
||||
command: |
|
||||
# gn.py tries to find a gclient root folder starting from the current dir.
|
||||
# When it fails and returns "None" path, the whole script fails. Let's "fix" it.
|
||||
touch .gclient
|
||||
# Another option would be to checkout "buildtools" inside the Electron checkout,
|
||||
# but then we would lint its contents (at least gn format), and it doesn't pass it.
|
||||
|
||||
cd src/electron
|
||||
node script/yarn install --frozen-lockfile
|
||||
node script/yarn lint
|
||||
- run:
|
||||
name: Run Script Typechecker
|
||||
command: |
|
||||
cd src/electron
|
||||
node script/yarn tsc -p tsconfig.script.json
|
||||
10
.circleci/config/package.json
Normal file
10
.circleci/config/package.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@electron/circleci-config",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fs-extra": "^10.1.0",
|
||||
"js-yaml": "^4.1.0"
|
||||
}
|
||||
}
|
||||
43
.circleci/config/yarn.lock
Normal file
43
.circleci/config/yarn.lock
Normal file
@@ -0,0 +1,43 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
argparse@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||
|
||||
fs-extra@^10.1.0:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
|
||||
integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^2.0.0"
|
||||
|
||||
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
|
||||
version "4.2.10"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
|
||||
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
jsonfile@^6.0.1:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
|
||||
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
|
||||
dependencies:
|
||||
universalify "^2.0.0"
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
universalify@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
|
||||
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
|
||||
178
.github/workflows/electron_woa_testing.yml
vendored
Normal file
178
.github/workflows/electron_woa_testing.yml
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
name: Electron WOA Testing
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: '**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
appveyor_job_id:
|
||||
description: 'Job Id of Appveyor WOA job to test'
|
||||
type: text
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
electron-woa-init:
|
||||
if: ${{ github.event_name == 'push' && github.repository == 'electron/electron' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dummy step for push event
|
||||
run: |
|
||||
echo "This job is a needed initialization step for Electron WOA testing. Another test result will appear once the electron-woa-testing build is done."
|
||||
|
||||
electron-woa-testing:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'electron/electron' }}
|
||||
runs-on: [self-hosted, woa]
|
||||
permissions:
|
||||
checks: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: LouisBrunner/checks-action@v1.1.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: electron-woa-testing
|
||||
status: in_progress
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
output: |
|
||||
{"summary":"Test In Progress","text_description":"See job details here: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}
|
||||
- name: Clean Workspace
|
||||
run: |
|
||||
Remove-Item * -Recurse -Force
|
||||
shell: powershell
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: src\electron
|
||||
fetch-depth: 0
|
||||
- name: Yarn install
|
||||
run: |
|
||||
cd src\electron
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
- name: Download and extract dist.zip for test
|
||||
run: |
|
||||
$localArtifactPath = "$pwd\dist.zip"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/dist.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -osrc\out\Default -y $localArtifactPath
|
||||
shell: powershell
|
||||
- name: Download and extract native test executables for test
|
||||
run: |
|
||||
$localArtifactPath = "src\out\Default\shell_browser_ui_unittests.exe"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/shell_browser_ui_unittests.exe"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
shell: powershell
|
||||
- name: Download and extract ffmpeg.zip for test
|
||||
run: |
|
||||
$localArtifactPath = "$pwd\ffmpeg.zip"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/ffmpeg.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -osrc\out\ffmpeg $localArtifactPath
|
||||
shell: powershell
|
||||
- name: Download node headers for test
|
||||
run: |
|
||||
$localArtifactPath = "src\node_headers.zip"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/node_headers.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
cd src
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y node_headers.zip
|
||||
shell: powershell
|
||||
- name: Download electron.lib for test
|
||||
run: |
|
||||
$localArtifactPath = "src\out\Default\electron.lib"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/electron.lib"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
shell: powershell
|
||||
# Uncomment the following block if pdb files are needed to debug issues
|
||||
# - name: Download pdb files for detailed stacktraces
|
||||
# if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
# run: |
|
||||
# try {
|
||||
# $localArtifactPath = "src\pdb.zip"
|
||||
# $serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/pdb.zip"
|
||||
# Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.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
|
||||
# }
|
||||
# shell: powershell
|
||||
- name: Setup node headers
|
||||
run: |
|
||||
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
|
||||
shell: powershell
|
||||
- name: Run Electron Main process tests
|
||||
run: |
|
||||
cd src
|
||||
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
node script/yarn test --runners=main --enable-logging --disable-features=CalculateNativeWinOcclusion
|
||||
env:
|
||||
ELECTRON_ENABLE_STACK_DUMPING: true
|
||||
ELECTRON_OUT_DIR: Default
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
ELECTRON_SKIP_NATIVE_MODULE_TESTS: true
|
||||
- name: Run Electron Remote based tests
|
||||
if: ${{ success() || failure() }}
|
||||
run: |
|
||||
cd src
|
||||
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
node script/yarn test --runners=remote --enable-logging --disable-features=CalculateNativeWinOcclusion
|
||||
env:
|
||||
ELECTRON_OUT_DIR: Default
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
ELECTRON_SKIP_NATIVE_MODULE_TESTS: true
|
||||
- name: Verify ffmpeg
|
||||
run: |
|
||||
cd src
|
||||
echo "Verifying non proprietary ffmpeg"
|
||||
python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
|
||||
shell: cmd
|
||||
- name: Kill processes left running from last test run
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
Get-Process | Where Name -Like "electron*" | Stop-Process
|
||||
Get-Process | Where Name -Like "msedge*" | Stop-Process
|
||||
shell: powershell
|
||||
- name: Delete user app data directories
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
Remove-Item -path $env:APPDATA/Electron* -Recurse -Force -ErrorAction Ignore
|
||||
shell: powershell
|
||||
- uses: LouisBrunner/checks-action@v1.1.1
|
||||
if: ${{ success() }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: electron-woa-testing
|
||||
conclusion: "${{ job.status }}"
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
output: |
|
||||
{"summary":"${{ job.status }}","text_description":"See job details here: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}
|
||||
- uses: LouisBrunner/checks-action@v1.1.1
|
||||
if: ${{ success() }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: electron-woa-testing
|
||||
conclusion: "${{ job.status }}"
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
output: |
|
||||
{"summary":"Job Succeeded","text_description":"See job details here: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}
|
||||
- uses: LouisBrunner/checks-action@v1.1.1
|
||||
if: ${{ ! success() }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: electron-woa-testing
|
||||
conclusion: "${{ job.status }}"
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
output: |
|
||||
{"summary":"Job Failed","text_description":"See job details here: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}
|
||||
20
.github/workflows/semantic.yml
vendored
Normal file
20
.github/workflows/semantic.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: "Check Semantic Commit"
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
main:
|
||||
name: Validate PR Title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: semantic-pull-request
|
||||
uses: amannn/action-semantic-pull-request@v4
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
validateSingleCommit: false
|
||||
@@ -23,7 +23,5 @@
|
||||
"br_spaces": 0
|
||||
},
|
||||
"single-h1": false,
|
||||
"no-inline-html": {
|
||||
"allowed_elements": ["br"]
|
||||
}
|
||||
"no-inline-html": false
|
||||
}
|
||||
|
||||
78
BUILD.gn
78
BUILD.gn
@@ -43,6 +43,7 @@ if (is_mac) {
|
||||
|
||||
if (is_linux) {
|
||||
import("//build/config/linux/pkg_config.gni")
|
||||
import("//tools/generate_stubs/rules.gni")
|
||||
|
||||
pkg_config("gio_unix") {
|
||||
packages = [ "gio-unix-2.0" ]
|
||||
@@ -54,6 +55,41 @@ if (is_linux) {
|
||||
"gdk-pixbuf-2.0",
|
||||
]
|
||||
}
|
||||
|
||||
generate_library_loader("libnotify_loader") {
|
||||
name = "LibNotifyLoader"
|
||||
output_h = "libnotify_loader.h"
|
||||
output_cc = "libnotify_loader.cc"
|
||||
header = "<libnotify/notify.h>"
|
||||
config = ":libnotify_config"
|
||||
|
||||
functions = [
|
||||
"notify_is_initted",
|
||||
"notify_init",
|
||||
"notify_get_server_caps",
|
||||
"notify_get_server_info",
|
||||
"notify_notification_new",
|
||||
"notify_notification_add_action",
|
||||
"notify_notification_set_image_from_pixbuf",
|
||||
"notify_notification_set_timeout",
|
||||
"notify_notification_set_urgency",
|
||||
"notify_notification_set_hint_string",
|
||||
"notify_notification_show",
|
||||
"notify_notification_close",
|
||||
]
|
||||
}
|
||||
|
||||
generate_stubs("electron_gtk_stubs") {
|
||||
sigs = [
|
||||
"shell/browser/ui/electron_gdk_pixbuf.sigs",
|
||||
"shell/browser/ui/electron_gtk.sigs",
|
||||
]
|
||||
extra_header = "shell/browser/ui/electron_gtk.fragment"
|
||||
output_name = "electron_gtk_stubs"
|
||||
public_deps = [ "//ui/gtk:gtk_config" ]
|
||||
logging_function = "LogNoop()"
|
||||
logging_include = "ui/gtk/log_noop.h"
|
||||
}
|
||||
}
|
||||
|
||||
declare_args() {
|
||||
@@ -253,31 +289,6 @@ copy("copy_shell_devtools_discovery_page") {
|
||||
outputs = [ "$target_gen_dir/shell_devtools_discovery_page.html" ]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
generate_library_loader("libnotify_loader") {
|
||||
name = "LibNotifyLoader"
|
||||
output_h = "libnotify_loader.h"
|
||||
output_cc = "libnotify_loader.cc"
|
||||
header = "<libnotify/notify.h>"
|
||||
config = ":libnotify_config"
|
||||
|
||||
functions = [
|
||||
"notify_is_initted",
|
||||
"notify_init",
|
||||
"notify_get_server_caps",
|
||||
"notify_get_server_info",
|
||||
"notify_notification_new",
|
||||
"notify_notification_add_action",
|
||||
"notify_notification_set_image_from_pixbuf",
|
||||
"notify_notification_set_timeout",
|
||||
"notify_notification_set_urgency",
|
||||
"notify_notification_set_hint_string",
|
||||
"notify_notification_show",
|
||||
"notify_notification_close",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
npm_action("electron_version_args") {
|
||||
script = "generate-version-json"
|
||||
|
||||
@@ -355,12 +366,14 @@ source_set("electron_lib") {
|
||||
"//chrome/app/resources:platform_locale_settings",
|
||||
"//components/autofill/core/common:features",
|
||||
"//components/certificate_transparency",
|
||||
"//components/embedder_support:browser_util",
|
||||
"//components/language/core/browser",
|
||||
"//components/net_log",
|
||||
"//components/network_hints/browser",
|
||||
"//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 +485,8 @@ source_set("electron_lib") {
|
||||
|
||||
if (is_linux) {
|
||||
deps += [
|
||||
"//build/config/linux/gtk:gtkprint",
|
||||
"//components/crash/content/browser",
|
||||
"//ui/gtk:gtk_config",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -534,6 +547,7 @@ source_set("electron_lib") {
|
||||
if (is_linux) {
|
||||
libs = [ "xshmfence" ]
|
||||
deps += [
|
||||
":electron_gtk_stubs",
|
||||
":libnotify_loader",
|
||||
"//build/config/linux/gtk",
|
||||
"//dbus",
|
||||
@@ -549,14 +563,13 @@ 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 += [
|
||||
@@ -694,6 +707,8 @@ source_set("electron_lib") {
|
||||
deps += [
|
||||
"//chrome/browser/resources/pdf:resources",
|
||||
"//components/pdf/browser",
|
||||
"//components/pdf/browser:interceptors",
|
||||
"//components/pdf/common",
|
||||
"//components/pdf/renderer",
|
||||
"//pdf:pdf_ppapi",
|
||||
]
|
||||
@@ -1048,7 +1063,6 @@ if (is_mac) {
|
||||
"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 = [
|
||||
@@ -1186,7 +1200,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" ]
|
||||
}
|
||||
|
||||
@@ -1265,6 +1279,10 @@ if (is_mac) {
|
||||
if (!is_component_build && is_component_ffmpeg) {
|
||||
configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
deps += [ "//sandbox/linux:chrome_sandbox" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
4
DEPS
4
DEPS
@@ -15,9 +15,9 @@ gclient_gn_args = [
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'98.0.4758.109',
|
||||
'100.0.4896.160',
|
||||
'node_version':
|
||||
'v16.13.0',
|
||||
'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 @@
|
||||
17.1.2
|
||||
18.3.7
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[](https://circleci.com/gh/electron/electron/tree/main)
|
||||
[](https://ci.appveyor.com/project/electron-bot/electron-ljo26/branch/main)
|
||||
[](https://discord.com/invite/electron)
|
||||
[](https://discord.com/invite/APGC3k5yaH)
|
||||
|
||||
:memo: Available Translations: 🇨🇳 🇧🇷 🇪🇸 🇯🇵 🇷🇺 🇫🇷 🇺🇸 🇩🇪.
|
||||
View these docs in other languages at [electron/i18n](https://github.com/electron/i18n/tree/master/content/).
|
||||
@@ -80,7 +80,7 @@ const child = proc.spawn(electron)
|
||||
|
||||
### Mirrors
|
||||
|
||||
- [China](https://npm.taobao.org/mirrors/electron)
|
||||
- [China](https://npmmirror.com/mirrors/electron)
|
||||
|
||||
## Documentation Translations
|
||||
|
||||
|
||||
68
appveyor.yml
68
appveyor.yml
@@ -11,7 +11,7 @@
|
||||
# - "TARGET_ARCH" Choose from {'ia32', 'x64', 'arm', 'arm64', 'mips64el'}.
|
||||
# Is used in some publishing scripts, but does NOT affect the Electron binary.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "NPM_CONFIG_ARCH" value.
|
||||
# - "UPLOAD_TO_S3" Set it to '1' upload a release to the S3 bucket.
|
||||
# - "UPLOAD_TO_STORAGE" Set it to '1' upload a release to the Azure bucket.
|
||||
# Otherwise the release will be uploaded to the Github Releases.
|
||||
# (The value is only checked if "ELECTRON_RELEASE" is defined.)
|
||||
#
|
||||
@@ -34,19 +34,10 @@ 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
|
||||
notifications:
|
||||
- provider: Webhook
|
||||
url: https://electron-mission-control.herokuapp.com/rest/appveyor-hook
|
||||
method: POST
|
||||
headers:
|
||||
x-mission-control-secret:
|
||||
secure: 90BLVPcqhJPG7d24v0q/RRray6W3wDQ8uVQlQjOHaBWkw1i8FoA1lsjr2C/v1dVok+tS2Pi6KxDctPUkwIb4T27u4RhvmcPzQhVpfwVJAG9oNtq+yKN7vzHfg7k/pojEzVdJpQLzeJGcSrZu7VY39Q==
|
||||
on_build_success: false
|
||||
on_build_failure: true
|
||||
on_build_status_changed: false
|
||||
build_script:
|
||||
- ps: >-
|
||||
if(($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -split "/")[0] -eq ($env:APPVEYOR_REPO_NAME -split "/")[0]) {
|
||||
@@ -66,6 +57,31 @@ build_script:
|
||||
- mkdir src
|
||||
- update_depot_tools.bat
|
||||
- ps: Move-Item $env:APPVEYOR_BUILD_FOLDER -Destination src\electron
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
}
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
@@ -129,21 +145,6 @@ build_script:
|
||||
Write-warning "Failed to add third_party\angle\.git; continuing anyway"
|
||||
}
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- cd src
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
|
||||
@@ -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,17 +220,20 @@ 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: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\UPLOAD_TO_S3) {
|
||||
Write-Output "Uploading Electron release distribution to s3"
|
||||
& python script\release\uploaders\upload.py --verbose --upload_to_s3
|
||||
if (Test-Path Env:\UPLOAD_TO_STORAGE) {
|
||||
Write-Output "Uploading Electron release distribution to azure"
|
||||
& python script\release\uploaders\upload.py --verbose --upload_to_storage
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
} 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
|
||||
node script/release/ci-release-build.js --job=electron-woa-testing --ci=GHA --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,121 +0,0 @@
|
||||
steps:
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy Files to: src/electron'
|
||||
inputs:
|
||||
TargetFolder: src/electron
|
||||
|
||||
- bash: |
|
||||
cd src/electron
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
displayName: 'Yarn install'
|
||||
|
||||
- bash: |
|
||||
export ZIP_DEST=$PWD/src/out/Default
|
||||
echo "##vso[task.setvariable variable=ZIP_DEST]$ZIP_DEST"
|
||||
mkdir -p $ZIP_DEST
|
||||
cd src/electron
|
||||
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=dist.zip --dest=$ZIP_DEST
|
||||
cd $ZIP_DEST
|
||||
unzip -o dist.zip
|
||||
xattr -cr Electron.app
|
||||
displayName: 'Download and unzip dist files for test'
|
||||
env:
|
||||
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
|
||||
|
||||
- bash: |
|
||||
export FFMPEG_ZIP_DEST=$PWD/src/out/ffmpeg
|
||||
mkdir -p $FFMPEG_ZIP_DEST
|
||||
cd src/electron
|
||||
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=ffmpeg.zip --dest=$FFMPEG_ZIP_DEST
|
||||
cd $FFMPEG_ZIP_DEST
|
||||
unzip -o ffmpeg.zip
|
||||
displayName: 'Download and unzip ffmpeg for test'
|
||||
env:
|
||||
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
|
||||
|
||||
- bash: |
|
||||
export NODE_HEADERS_DEST=$PWD/src/out/Default/gen
|
||||
mkdir -p $NODE_HEADERS_DEST
|
||||
cd src/electron
|
||||
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=node_headers.tar.gz --dest=$NODE_HEADERS_DEST
|
||||
cd $NODE_HEADERS_DEST
|
||||
tar xzf node_headers.tar.gz
|
||||
displayName: 'Download and untar node header files for test'
|
||||
env:
|
||||
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
|
||||
|
||||
- bash: |
|
||||
export CROSS_ARCH_SNAPSHOTS=$PWD/src/out/Default/cross-arch-snapshots
|
||||
mkdir -p $CROSS_ARCH_SNAPSHOTS
|
||||
cd src/electron
|
||||
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=cross-arch-snapshots/snapshot_blob.bin --dest=$CROSS_ARCH_SNAPSHOTS
|
||||
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=cross-arch-snapshots/v8_context_snapshot.arm64.bin --dest=$CROSS_ARCH_SNAPSHOTS
|
||||
displayName: 'Download cross arch snapshot files'
|
||||
env:
|
||||
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
|
||||
|
||||
- bash: |
|
||||
cd src
|
||||
export ELECTRON_OUT_DIR=Default
|
||||
export npm_config_arch=arm64
|
||||
(cd electron && node script/yarn test --enable-logging --runners main)
|
||||
displayName: 'Run Electron main tests'
|
||||
timeoutInMinutes: 20
|
||||
env:
|
||||
ELECTRON_DISABLE_SECURITY_WARNINGS: 1
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
|
||||
- bash: |
|
||||
cd src
|
||||
export ELECTRON_OUT_DIR=Default
|
||||
export npm_config_arch=arm64
|
||||
(cd electron && node script/yarn test --enable-logging --runners remote)
|
||||
displayName: 'Run Electron remote tests'
|
||||
timeoutInMinutes: 20
|
||||
condition: succeededOrFailed()
|
||||
env:
|
||||
ELECTRON_DISABLE_SECURITY_WARNINGS: 1
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
|
||||
- bash: |
|
||||
cd src
|
||||
python electron/script/verify-ffmpeg.py --source-root "$PWD" --build-dir out/Default --ffmpeg-path out/ffmpeg
|
||||
displayName: Verify non proprietary ffmpeg
|
||||
timeoutInMinutes: 5
|
||||
condition: succeededOrFailed()
|
||||
env:
|
||||
TARGET_ARCH: arm64
|
||||
|
||||
- bash: |
|
||||
cd src
|
||||
echo Verify cross arch snapshot
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --snapshot-files-dir $PWD/out/Default/cross-arch-snapshots
|
||||
displayName: Verify cross arch snapshot
|
||||
timeoutInMinutes: 5
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish Test Results'
|
||||
inputs:
|
||||
testResultsFiles: '*.xml'
|
||||
|
||||
searchFolder: '$(System.DefaultWorkingDirectory)/src/junit/'
|
||||
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- bash: killall Electron || echo "No Electron processes left running"
|
||||
displayName: 'Kill processes left running from last test run'
|
||||
condition: always()
|
||||
|
||||
- bash: |
|
||||
rm -rf ~/Library/Application\ Support/Electron*
|
||||
rm -rf ~/Library/Application\ Support/electron*
|
||||
displayName: 'Delete user app data directories'
|
||||
condition: always()
|
||||
|
||||
- task: mspremier.PostBuildCleanup.PostBuildCleanup-task.PostBuildCleanup@3
|
||||
displayName: 'Clean Agent Directories'
|
||||
|
||||
condition: always()
|
||||
@@ -1,129 +0,0 @@
|
||||
steps:
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy Files to: src\electron'
|
||||
inputs:
|
||||
TargetFolder: src\electron
|
||||
|
||||
- script: |
|
||||
cd src\electron
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
displayName: 'Yarn install'
|
||||
|
||||
- powershell: |
|
||||
$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
|
||||
displayName: 'Download and extract dist.zip for test'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$pwd\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'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$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
|
||||
displayName: 'Download and extract ffmpeg.zip for test'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$pwd\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
|
||||
& "${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"
|
||||
$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)
|
||||
|
||||
- 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
|
||||
displayName: 'Setup node headers'
|
||||
|
||||
- script: |
|
||||
cd 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
|
||||
displayName: 'Run Electron Main process tests'
|
||||
env:
|
||||
ELECTRON_ENABLE_STACK_DUMPING: true
|
||||
ELECTRON_OUT_DIR: Default
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
|
||||
- script: |
|
||||
cd src
|
||||
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
node script/yarn test --runners=remote --enable-logging --disable-features=CalculateNativeWinOcclusion
|
||||
displayName: 'Run Electron Remote based tests'
|
||||
env:
|
||||
ELECTRON_OUT_DIR: Default
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
condition: always()
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish Test Results'
|
||||
inputs:
|
||||
testResultsFiles: '*.xml'
|
||||
searchFolder: '$(System.DefaultWorkingDirectory)/src/junit/'
|
||||
condition: always()
|
||||
|
||||
- script: |
|
||||
cd 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'
|
||||
|
||||
- powershell: |
|
||||
Get-Process | Where Name –Like "electron*" | Stop-Process
|
||||
Get-Process | Where Name –Like "msedge*" | Stop-Process
|
||||
displayName: 'Kill processes left running from last test run'
|
||||
condition: always()
|
||||
|
||||
- powershell: |
|
||||
Remove-Item -path $env:APPDATA/Electron* -Recurse -Force -ErrorAction Ignore
|
||||
displayName: 'Delete user app data directories'
|
||||
condition: always()
|
||||
@@ -2,10 +2,9 @@ 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 = 101
|
||||
node_module_version = 103
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_typed_array_max_size_in_heap = 0
|
||||
v8_embedder_string = "-electron.0"
|
||||
|
||||
# TODO: this breaks mksnapshot
|
||||
@@ -14,11 +13,17 @@ 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"
|
||||
|
||||
enable_basic_printing = true
|
||||
|
||||
# Removes DLLs from the build, which are only meant to be used for Chromium development.
|
||||
# See https://github.com/electron/electron/pull/17985
|
||||
angle_enable_vulkan_validation_layers = false
|
||||
dawn_enable_vulkan_validation_layers = false
|
||||
|
||||
|
||||
@@ -24,7 +24,11 @@ template("extract_symbols") {
|
||||
assert(defined(invoker.binary), "Need binary to dump")
|
||||
assert(defined(invoker.symbol_dir), "Need directory for symbol output")
|
||||
|
||||
dump_syms_label = "//third_party/breakpad:dump_syms($host_toolchain)"
|
||||
if (host_os == "win" && target_cpu == "x86") {
|
||||
dump_syms_label = "//third_party/breakpad:dump_syms(//build/toolchain/win:win_clang_x64)"
|
||||
} else {
|
||||
dump_syms_label = "//third_party/breakpad:dump_syms($host_toolchain)"
|
||||
}
|
||||
dump_syms_binary = get_label_info(dump_syms_label, "root_out_dir") +
|
||||
"/dump_syms$_host_executable_suffix"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
from __future__ import with_statement
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import contextlib
|
||||
import sys
|
||||
import os
|
||||
import optparse
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
sys.path.append("%s/../../build" % os.path.dirname(os.path.realpath(__file__)))
|
||||
|
||||
@@ -33,36 +36,56 @@ def calculate_hash(root):
|
||||
return CalculateHash('.', None)
|
||||
|
||||
def windows_installed_software():
|
||||
import win32com.client
|
||||
strComputer = "."
|
||||
objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
|
||||
objSWbemServices = objWMIService.ConnectServer(strComputer, "root\cimv2")
|
||||
colItems = objSWbemServices.ExecQuery("Select * from Win32_Product")
|
||||
items = []
|
||||
powershell_command = [
|
||||
"Get-CimInstance",
|
||||
"-Namespace",
|
||||
"root\cimv2",
|
||||
"-Class",
|
||||
"Win32_product",
|
||||
"|",
|
||||
"Select",
|
||||
"vendor,",
|
||||
"description,",
|
||||
"@{l='install_location';e='InstallLocation'},",
|
||||
"@{l='install_date';e='InstallDate'},",
|
||||
"@{l='install_date_2';e='InstallDate2'},",
|
||||
"caption,",
|
||||
"version,",
|
||||
"name,",
|
||||
"@{l='sku_number';e='SKUNumber'}",
|
||||
"|",
|
||||
"ConvertTo-Json",
|
||||
]
|
||||
|
||||
for objItem in colItems:
|
||||
item = {}
|
||||
if objItem.Caption:
|
||||
item['caption'] = objItem.Caption
|
||||
if objItem.Caption:
|
||||
item['description'] = objItem.Description
|
||||
if objItem.InstallDate:
|
||||
item['install_date'] = objItem.InstallDate
|
||||
if objItem.InstallDate2:
|
||||
item['install_date_2'] = objItem.InstallDate2
|
||||
if objItem.InstallLocation:
|
||||
item['install_location'] = objItem.InstallLocation
|
||||
if objItem.Name:
|
||||
item['name'] = objItem.Name
|
||||
if objItem.SKUNumber:
|
||||
item['sku_number'] = objItem.SKUNumber
|
||||
if objItem.Vendor:
|
||||
item['vendor'] = objItem.Vendor
|
||||
if objItem.Version:
|
||||
item['version'] = objItem.Version
|
||||
items.append(item)
|
||||
proc = subprocess.Popen(
|
||||
["powershell.exe", "-Command", "-"],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
|
||||
return items
|
||||
stdout, _ = proc.communicate(" ".join(powershell_command).encode("utf-8"))
|
||||
|
||||
if proc.returncode != 0:
|
||||
raise RuntimeError("Failed to get list of installed software")
|
||||
|
||||
# On AppVeyor there's other output related to PSReadline,
|
||||
# so grab only the JSON output and ignore everything else
|
||||
json_match = re.match(
|
||||
r".*(\[.*{.*}.*\]).*", stdout.decode("utf-8"), re.DOTALL
|
||||
)
|
||||
|
||||
if not json_match:
|
||||
raise RuntimeError(
|
||||
"Couldn't find JSON output for list of installed software"
|
||||
)
|
||||
|
||||
# Filter out missing keys
|
||||
return list(
|
||||
map(
|
||||
lambda info: {k: info[k] for k in info if info[k]},
|
||||
json.loads(json_match.group(1)),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def windows_profile():
|
||||
@@ -89,7 +112,7 @@ def windows_profile():
|
||||
|
||||
def main(options):
|
||||
if sys.platform == 'win32':
|
||||
with open(options.output_json, 'wb') as f:
|
||||
with open(options.output_json, 'w') as f:
|
||||
json.dump(windows_profile(), f)
|
||||
else:
|
||||
raise OSError("Unsupported OS")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -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) {
|
||||
@@ -243,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",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -259,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",
|
||||
@@ -275,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",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -297,11 +298,21 @@ static_library("chrome") {
|
||||
|
||||
if (enable_pdf_viewer) {
|
||||
sources += [
|
||||
"//chrome/browser/pdf/chrome_pdf_stream_delegate.cc",
|
||||
"//chrome/browser/pdf/chrome_pdf_stream_delegate.h",
|
||||
"//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/browser/plugins/pdf_iframe_navigation_throttle.cc",
|
||||
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.h",
|
||||
"//chrome/renderer/pepper/chrome_pdf_print_client.cc",
|
||||
"//chrome/renderer/pepper/chrome_pdf_print_client.h",
|
||||
]
|
||||
deps += [
|
||||
"//components/pdf/browser",
|
||||
"//components/pdf/renderer",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,15 +340,6 @@ source_set("plugins") {
|
||||
"//chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc",
|
||||
"//chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h",
|
||||
]
|
||||
deps += [
|
||||
"//media:media_buildflags",
|
||||
"//ppapi/buildflags",
|
||||
"//ppapi/proxy:ipc",
|
||||
"//services/device/public/mojom",
|
||||
]
|
||||
if (enable_pdf_viewer) {
|
||||
deps += [ "//components/pdf/browser" ]
|
||||
}
|
||||
|
||||
# renderer side
|
||||
sources += [
|
||||
@@ -348,17 +350,18 @@ source_set("plugins") {
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc",
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.h",
|
||||
]
|
||||
if (enable_pdf_viewer) {
|
||||
deps += [ "//components/pdf/renderer" ]
|
||||
}
|
||||
|
||||
deps += [
|
||||
"//components/strings",
|
||||
"//media:media_buildflags",
|
||||
"//ppapi/buildflags",
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/proxy:ipc",
|
||||
"//ppapi/shared_impl",
|
||||
"//services/device/public/mojom",
|
||||
"//skia",
|
||||
"//storage/browser",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { app, dialog, BrowserWindow, shell, ipcMain } from 'electron';
|
||||
import { shell } from 'electron/common';
|
||||
import { app, dialog, BrowserWindow, ipcMain } from 'electron/main';
|
||||
import * as path from 'path';
|
||||
import * as url from 'url';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as electron from 'electron';
|
||||
import * as electron from 'electron/main';
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ipcRenderer, contextBridge } from 'electron';
|
||||
import { ipcRenderer, contextBridge } from 'electron/renderer';
|
||||
|
||||
const policy = window.trustedTypes.createPolicy('electron-default-app', {
|
||||
// we trust the SVG contents
|
||||
|
||||
@@ -70,9 +70,6 @@ an issue:
|
||||
* [Windows Store](tutorial/windows-store-guide.md)
|
||||
* [Snapcraft](tutorial/snapcraft.md)
|
||||
* [Updates](tutorial/updates.md)
|
||||
* [Deploying an Update Server](tutorial/updates.md#deploying-an-update-server)
|
||||
* [Implementing Updates in Your App](tutorial/updates.md#implementing-updates-in-your-app)
|
||||
* [Applying Updates](tutorial/updates.md#applying-updates)
|
||||
* [Getting Support](tutorial/support.md)
|
||||
|
||||
## Detailed Tutorials
|
||||
@@ -106,7 +103,6 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
* [`File` Object](api/file-object.md)
|
||||
* [`<webview>` Tag](api/webview-tag.md)
|
||||
* [`window.open` Function](api/window-open.md)
|
||||
* [`BrowserWindowProxy` Object](api/browser-window-proxy.md)
|
||||
|
||||
### Modules for the Main Process:
|
||||
|
||||
|
||||
@@ -837,6 +837,8 @@ Returns `Object`:
|
||||
|
||||
* `categories` [JumpListCategory[]](structures/jump-list-category.md) | `null` - Array of `JumpListCategory` objects.
|
||||
|
||||
Returns `string`
|
||||
|
||||
Sets or removes a custom Jump List for the application, and returns one of the
|
||||
following strings:
|
||||
|
||||
|
||||
@@ -70,5 +70,31 @@ The `bounds` of this BrowserView instance as `Object`.
|
||||
|
||||
#### `view.setBackgroundColor(color)` _Experimental_
|
||||
|
||||
* `color` string - Color in `#aarrggbb` or `#argb` form. The alpha channel is
|
||||
optional.
|
||||
* `color` string - Color in Hex, RGB, ARGB, HSL, HSLA or named CSS color format. The alpha channel is
|
||||
optional for the hex type.
|
||||
|
||||
Examples of valid `color` values:
|
||||
|
||||
* Hex
|
||||
* #fff (RGB)
|
||||
* #ffff (ARGB)
|
||||
* #ffffff (RRGGBB)
|
||||
* #ffffffff (AARRGGBB)
|
||||
* RGB
|
||||
* rgb\(([\d]+),\s*([\d]+),\s*([\d]+)\)
|
||||
* e.g. rgb(255, 255, 255)
|
||||
* RGBA
|
||||
* rgba\(([\d]+),\s*([\d]+),\s*([\d]+),\s*([\d.]+)\)
|
||||
* e.g. rgba(255, 255, 255, 1.0)
|
||||
* HSL
|
||||
* hsl\((-?[\d.]+),\s*([\d.]+)%,\s*([\d.]+)%\)
|
||||
* e.g. hsl(200, 20%, 50%)
|
||||
* HSLA
|
||||
* hsla\((-?[\d.]+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)
|
||||
* e.g. hsla(200, 20%, 50%, 0.5)
|
||||
* Color name
|
||||
* Options are listed in [SkParseColor.cpp](https://source.chromium.org/chromium/chromium/src/+/main:third_party/skia/src/utils/SkParseColor.cpp;l=11-152;drc=eea4bf52cb0d55e2a39c828b017c80a5ee054148)
|
||||
* Similar to CSS Color Module Level 3 keywords, but case-sensitive.
|
||||
* e.g. `blueviolet` or `red`
|
||||
|
||||
**Note:** Hex format with alpha takes `AARRGGBB` or `ARGB`, _not_ `RRGGBBA` or `RGA`.
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
## Class: BrowserWindowProxy
|
||||
|
||||
> Manipulate the child browser window
|
||||
|
||||
Process: [Renderer](../glossary.md#renderer-process)<br />
|
||||
_This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API._
|
||||
|
||||
The `BrowserWindowProxy` object is returned from `window.open` and provides
|
||||
limited functionality with the child window.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
The `BrowserWindowProxy` object has the following instance methods:
|
||||
|
||||
#### `win.blur()`
|
||||
|
||||
Removes focus from the child window.
|
||||
|
||||
#### `win.close()`
|
||||
|
||||
Forcefully closes the child window without calling its unload event.
|
||||
|
||||
#### `win.eval(code)`
|
||||
|
||||
* `code` string
|
||||
|
||||
Evaluates the code in the child window.
|
||||
|
||||
#### `win.focus()`
|
||||
|
||||
Focuses the child window (brings the window to front).
|
||||
|
||||
#### `win.print()`
|
||||
|
||||
Invokes the print dialog on the child window.
|
||||
|
||||
#### `win.postMessage(message, targetOrigin)`
|
||||
|
||||
* `message` any
|
||||
* `targetOrigin` string
|
||||
|
||||
Sends a message to the child window with the specified origin or `*` for no
|
||||
origin preference.
|
||||
|
||||
In addition to these methods, the child window implements `window.opener` object
|
||||
with no properties and a single method.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The `BrowserWindowProxy` object has the following instance properties:
|
||||
|
||||
#### `win.closed`
|
||||
|
||||
A `boolean` that is set to true after the child window gets closed.
|
||||
@@ -66,6 +66,18 @@ 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.
|
||||
|
||||
Some examples of valid `backgroundColor` values include:
|
||||
|
||||
```js
|
||||
const win = new BrowserWindow()
|
||||
win.setBackgroundColor('hsl(230, 100%, 50%)')
|
||||
win.setBackgroundColor('rgb(255, 145, 145)')
|
||||
win.setBackgroundColor('#ff00a3')
|
||||
win.setBackgroundColor('blueviolet')
|
||||
```
|
||||
|
||||
For more information about these color types see valid options in [win.setBackgroundColor](browser-window.md#winsetbackgroundcolorbackgroundcolor).
|
||||
|
||||
## Parent and child windows
|
||||
|
||||
By using `parent` option, you can create child windows:
|
||||
@@ -199,9 +211,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `enableLargerThanScreen` boolean (optional) - Enable the window to be resized larger
|
||||
than screen. Only relevant for macOS, as other OSes allow
|
||||
larger-than-screen windows by default. Default is `false`.
|
||||
* `backgroundColor` string (optional) - Window's background color as a hexadecimal value,
|
||||
like `#66CD00` or `#FFF` or `#80FFFFFF` (alpha in #AARRGGBB format is supported if
|
||||
`transparent` is set to `true`). Default is `#FFF` (white).
|
||||
* `backgroundColor` string (optional) - The window's background color in Hex, RGB, RGBA, HSL, HSLA or named CSS color format. Alpha in #AARRGGBB format is supported if `transparent` is set to `true`. Default is `#FFF` (white). See [win.setBackgroundColor](browser-window.md#winsetbackgroundcolorbackgroundcolor) for more information.
|
||||
* `hasShadow` boolean (optional) - Whether window should have a shadow. Default is `true`.
|
||||
* `opacity` number (optional) - Set the initial opacity of the window, between 0.0 (fully
|
||||
transparent) and 1.0 (fully opaque). This is only implemented on Windows and macOS.
|
||||
@@ -341,9 +351,6 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
[Chrome Content Scripts][chrome-content-scripts]. You can access this
|
||||
context in the dev tools by selecting the 'Electron Isolated Context'
|
||||
entry in the combo box at the top of the Console tab.
|
||||
* `nativeWindowOpen` boolean (optional) - Whether to use native
|
||||
`window.open()`. Defaults to `true`. Child windows will always have node
|
||||
integration disabled unless `nodeIntegrationInSubFrames` is true.
|
||||
* `webviewTag` boolean (optional) - Whether to enable the [`<webview>` tag](webview-tag.md).
|
||||
Defaults to `false`. **Note:** The
|
||||
`preload` script configured for the `<webview>` will have node integration
|
||||
@@ -391,7 +398,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
contain the layout of the document—without requiring scrolling. Enabling
|
||||
this will cause the `preferred-size-changed` event to be emitted on the
|
||||
`WebContents` when the preferred size changes. Default is `false`.
|
||||
* `titleBarOverlay` 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`.
|
||||
* `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.
|
||||
@@ -457,7 +464,7 @@ window.onbeforeunload = (e) => {
|
||||
// a non-void value will silently cancel the close.
|
||||
// It is recommended to use the dialog API to let the user confirm closing the
|
||||
// application.
|
||||
e.returnValue = false // equivalent to `return false` but not recommended
|
||||
e.returnValue = false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -995,12 +1002,33 @@ APIs like `win.setSize`.
|
||||
|
||||
#### `win.setBackgroundColor(backgroundColor)`
|
||||
|
||||
* `backgroundColor` string - Window's background color as a hexadecimal value,
|
||||
like `#66CD00` or `#FFF` or `#80FFFFFF` (alpha is supported if `transparent`
|
||||
is `true`). Default is `#FFF` (white).
|
||||
* `backgroundColor` string - Color in Hex, RGB, RGBA, HSL, HSLA or named CSS color format. The alpha channel is optional for the hex type.
|
||||
|
||||
Sets the background color of the window. See [Setting
|
||||
`backgroundColor`](#setting-the-backgroundcolor-property).
|
||||
Examples of valid `backgroundColor` values:
|
||||
|
||||
* Hex
|
||||
* #fff (shorthand RGB)
|
||||
* #ffff (shorthand ARGB)
|
||||
* #ffffff (RGB)
|
||||
* #ffffffff (ARGB)
|
||||
* RGB
|
||||
* rgb\(([\d]+),\s*([\d]+),\s*([\d]+)\)
|
||||
* e.g. rgb(255, 255, 255)
|
||||
* RGBA
|
||||
* rgba\(([\d]+),\s*([\d]+),\s*([\d]+),\s*([\d.]+)\)
|
||||
* e.g. rgba(255, 255, 255, 1.0)
|
||||
* HSL
|
||||
* hsl\((-?[\d.]+),\s*([\d.]+)%,\s*([\d.]+)%\)
|
||||
* e.g. hsl(200, 20%, 50%)
|
||||
* HSLA
|
||||
* hsla\((-?[\d.]+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)
|
||||
* e.g. hsla(200, 20%, 50%, 0.5)
|
||||
* Color name
|
||||
* Options are listed in [SkParseColor.cpp](https://source.chromium.org/chromium/chromium/src/+/main:third_party/skia/src/utils/SkParseColor.cpp;l=11-152;drc=eea4bf52cb0d55e2a39c828b017c80a5ee054148)
|
||||
* Similar to CSS Color Module Level 3 keywords, but case-sensitive.
|
||||
* e.g. `blueviolet` or `red`
|
||||
|
||||
Sets the background color of the window. See [Setting `backgroundColor`](#setting-the-backgroundcolor-property).
|
||||
|
||||
#### `win.previewFile(path[, displayName])` _macOS_
|
||||
|
||||
@@ -1044,8 +1072,11 @@ 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-the-backgroundcolor-property).
|
||||
Returns `string` - Gets the background color of the window in Hex (`#RRGGBB`) format.
|
||||
|
||||
See [Setting `backgroundColor`](#setting-the-backgroundcolor-property).
|
||||
|
||||
**Note:** The alpha value is _not_ returned alongside the red, green, and blue values.
|
||||
|
||||
#### `win.setContentBounds(bounds[, animate])`
|
||||
|
||||
@@ -1811,6 +1842,16 @@ with `addBrowserView` or `setBrowserView`.
|
||||
**Note:** The BrowserView API is currently experimental and may change or be
|
||||
removed in future Electron releases.
|
||||
|
||||
#### `win.setTitleBarOverlay(options)` _Windows_
|
||||
|
||||
* `options` Object
|
||||
* `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled.
|
||||
* `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled.
|
||||
* `height` Integer (optional) _Windows_ - The height of the title bar and Window Controls Overlay in pixels.
|
||||
|
||||
On a Window with Window Controls Overlay already enabled, this method updates
|
||||
the style of the title bar overlay.
|
||||
|
||||
[runtime-enabled-features]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70
|
||||
[page-visibility-api]: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
|
||||
[quick-look]: https://en.wikipedia.org/wiki/Quick_Look
|
||||
|
||||
@@ -27,6 +27,7 @@ Or use a 3rd party hosted solution:
|
||||
* [Backtrace](https://backtrace.io/electron/)
|
||||
* [Sentry](https://docs.sentry.io/clients/electron)
|
||||
* [BugSplat](https://www.bugsplat.com/docs/platforms/electron)
|
||||
* [Bugsnag](https://docs.bugsnag.com/platforms/electron/)
|
||||
|
||||
Crash reports are stored temporarily before being uploaded in a directory
|
||||
underneath the app's user data directory, called 'Crashpad'. You can override
|
||||
|
||||
@@ -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_
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@ Only `chrome.storage.local` is supported; `chrome.storage.sync` and
|
||||
The following methods of `chrome.tabs` are supported:
|
||||
|
||||
- `chrome.tabs.sendMessage`
|
||||
- `chrome.tabs.reload`
|
||||
- `chrome.tabs.executeScript`
|
||||
- `chrome.tabs.update` (partial support)
|
||||
- supported properties: `url`, `muted`.
|
||||
|
||||
@@ -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,10 +1,3 @@
|
||||
---
|
||||
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.
|
||||
@@ -16,9 +9,7 @@ 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.
|
||||
|
||||
For usage examples, check out the [IPC tutorial].
|
||||
|
||||
## Sending messages
|
||||
## 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.
|
||||
@@ -30,6 +21,36 @@ 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:
|
||||
@@ -38,7 +59,7 @@ The `ipcMain` module has the following method to listen for events:
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` [IpcMainEvent][ipc-main-event]
|
||||
* `event` IpcMainEvent
|
||||
* `...args` any[]
|
||||
|
||||
Listens to `channel`, when a new message arrives `listener` would be called with
|
||||
@@ -48,7 +69,7 @@ Listens to `channel`, when a new message arrives `listener` would be called with
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` [IpcMainEvent][ipc-main-event]
|
||||
* `event` IpcMainEvent
|
||||
* `...args` any[]
|
||||
|
||||
Adds a one time `listener` function for the event. This `listener` is invoked
|
||||
@@ -72,8 +93,8 @@ Removes listeners of the specified `channel`.
|
||||
### `ipcMain.handle(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `event` IpcMainInvokeEvent
|
||||
* `...args` any[]
|
||||
|
||||
Adds a handler for an `invoke`able IPC. This handler will be called whenever a
|
||||
@@ -83,14 +104,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 title='Main Process'
|
||||
```js
|
||||
// Main process
|
||||
ipcMain.handle('my-invokable-ipc', async (event, ...args) => {
|
||||
const result = await somePromise(...args)
|
||||
return result
|
||||
})
|
||||
```
|
||||
|
||||
```js title='Renderer Process'
|
||||
// Renderer process
|
||||
async () => {
|
||||
const result = await ipcRenderer.invoke('my-invokable-ipc', arg1, arg2)
|
||||
// ...
|
||||
@@ -109,7 +130,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[]
|
||||
|
||||
@@ -125,16 +146,13 @@ 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`][ipc-main-event] structure docs.
|
||||
in the [`ipc-main-event`](structures/ipc-main-event.md) structure docs.
|
||||
|
||||
## IpcMainInvokeEvent object
|
||||
|
||||
The documentation for the `event` object passed to `handle` callbacks can be
|
||||
found in the [`ipc-main-invoke-event`][ipc-main-invoke-event]
|
||||
found in the [`ipc-main-invoke-event`](structures/ipc-main-invoke-event.md)
|
||||
structure docs.
|
||||
|
||||
[IPC tutorial]: ../tutorial/ipc.md
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[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
|
||||
[web-contents-send]: web-contents.md#contentssendchannel-args
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
---
|
||||
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.
|
||||
@@ -16,7 +9,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 [IPC tutorial](../tutorial/ipc.md) for code examples.
|
||||
See [ipcMain](ipc-main.md) for code examples.
|
||||
|
||||
## Methods
|
||||
|
||||
@@ -77,7 +70,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).
|
||||
|
||||
@@ -105,7 +98,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:
|
||||
|
||||
@@ -131,11 +124,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.
|
||||
|
||||
@@ -147,13 +140,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])`
|
||||
|
||||
@@ -165,7 +158,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:
|
||||
@@ -204,7 +197,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
|
||||
|
||||
@@ -14,7 +14,7 @@ See [`Menu`](menu.md) for examples.
|
||||
* `menuItem` MenuItem
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) | undefined - This will not be defined if no window is open.
|
||||
* `event` [KeyboardEvent](structures/keyboard-event.md)
|
||||
* `role` string (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `toggleSpellChecker`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `shareMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
|
||||
* `role` string (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `toggleSpellChecker`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, 'showSubstitutions', 'toggleSmartQuotes', 'toggleSmartDashes', 'toggleTextReplacement', `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `shareMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
|
||||
`click` property will be ignored. See [roles](#roles).
|
||||
* `type` string (optional) - Can be `normal`, `separator`, `submenu`, `checkbox` or
|
||||
`radio`.
|
||||
@@ -100,6 +100,10 @@ The following additional roles are available on _macOS_:
|
||||
* `hide` - Map to the `hide` action.
|
||||
* `hideOthers` - Map to the `hideOtherApplications` action.
|
||||
* `unhide` - Map to the `unhideAllApplications` action.
|
||||
* `showSubstitutions` - Map to the `orderFrontSubstitutionsPanel` action.
|
||||
* `toggleSmartQuotes` - Map to the `toggleAutomaticQuoteSubstitution` action.
|
||||
* `toggleSmartDashes` - Map to the `toggleAutomaticDashSubstitution` action.
|
||||
* `toggleTextReplacement` - Map to the `toggleAutomaticTextReplacement` action.
|
||||
* `startSpeaking` - Map to the `startSpeaking` action.
|
||||
* `stopSpeaking` - Map to the `stopSpeaking` action.
|
||||
* `front` - Map to the `arrangeInFront` action.
|
||||
@@ -120,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
|
||||
|
||||
|
||||
@@ -67,3 +67,8 @@ or is being instructed to show a high-contrast UI.
|
||||
|
||||
A `boolean` for if the OS / Chromium currently has an inverted color scheme
|
||||
or is being instructed to use an inverted color scheme.
|
||||
|
||||
### `nativeTheme.inForcedColorsMode` _Windows_ _Readonly_
|
||||
|
||||
A `boolean` indicating whether Chromium is in forced colors mode, controlled by system accessibility settings.
|
||||
Currently, Windows high contrast is the only system setting that triggers forced colors mode.
|
||||
|
||||
@@ -178,7 +178,6 @@ Returns an object with V8 heap statistics. Note that all statistics are reported
|
||||
Returns `Object`:
|
||||
|
||||
* `allocated` Integer - Size of all allocated objects in Kilobytes.
|
||||
* `marked` Integer - Size of all marked objects in Kilobytes.
|
||||
* `total` Integer - Total allocated space in Kilobytes.
|
||||
|
||||
Returns an object with Blink memory information.
|
||||
|
||||
@@ -18,9 +18,9 @@ The `safeStorage` module has the following methods:
|
||||
|
||||
Returns `boolean` - Whether encryption is available.
|
||||
|
||||
On Linux, returns true if the secret key is
|
||||
available. On MacOS, returns true if Keychain is available.
|
||||
On Windows, returns true with no other preconditions.
|
||||
On Linux, returns true if the app has emitted the `ready` event and the secret key is available.
|
||||
On MacOS, returns true if Keychain is available.
|
||||
On Windows, returns true once the app has emitted the `ready` event.
|
||||
|
||||
### `safeStorage.encryptString(plainText)`
|
||||
|
||||
|
||||
@@ -868,6 +868,20 @@ this session just before normal `preload` scripts run.
|
||||
Returns `string[]` an array of paths to preload scripts that have been
|
||||
registered.
|
||||
|
||||
#### `ses.setCodeCachePath(path)`
|
||||
|
||||
* `path` String - Absolute path to store the v8 generated JS code cache from the renderer.
|
||||
|
||||
Sets the directory to store the generated JS [code cache](https://v8.dev/blog/code-caching-for-devs) for this session. The directory is not required to be created by the user before this call, the runtime will create if it does not exist otherwise will use the existing directory. If directory cannot be created, then code cache will not be used and all operations related to code cache will fail silently inside the runtime. By default, the directory will be `Code Cache` under the
|
||||
respective user data folder.
|
||||
|
||||
#### `ses.clearCodeCaches(options)`
|
||||
|
||||
* `options` Object
|
||||
* `urls` String[] (optional) - An array of url corresponding to the resource whose generated code cache needs to be removed. If the list is empty then all entries in the cache directory will be removed.
|
||||
|
||||
Returns `Promise<void>` - resolves when the code cache clear operation is complete.
|
||||
|
||||
#### `ses.setSpellCheckerEnabled(enable)`
|
||||
|
||||
* `enable` boolean
|
||||
|
||||
@@ -7,17 +7,3 @@
|
||||
the `enctype` attribute of the submitted HTML form.
|
||||
* `boundary` string (optional) - The boundary used to separate multiple parts of
|
||||
the message. Only valid when `contentType` is `multipart/form-data`.
|
||||
|
||||
Note that keys starting with `--` are not currently supported. For example, this will errantly submit as `multipart/form-data` when `nativeWindowOpen` is set to `false` in webPreferences:
|
||||
|
||||
```html
|
||||
<form
|
||||
target="_blank"
|
||||
method="POST"
|
||||
enctype="application/x-www-form-urlencoded"
|
||||
action="https://postman-echo.com/post"
|
||||
>
|
||||
<input type="text" name="--theKey">
|
||||
<input type="submit">
|
||||
</form>
|
||||
```
|
||||
|
||||
@@ -84,7 +84,7 @@ that contains the user information dictionary sent along with the notification.
|
||||
|
||||
### `systemPreferences.subscribeNotification(event, callback)` _macOS_
|
||||
|
||||
* `event` string
|
||||
* `event` string | null
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record<string, unknown>
|
||||
@@ -109,9 +109,11 @@ example values of `event` are:
|
||||
* `AppleColorPreferencesChangedNotification`
|
||||
* `AppleShowScrollBarsSettingChanged`
|
||||
|
||||
If `event` is null, the `NSDistributedNotificationCenter` doesn’t use it as criteria for delivery to the observer. See [docs](https://developer.apple.com/documentation/foundation/nsnotificationcenter/1411723-addobserverforname?language=objc) for more information.
|
||||
|
||||
### `systemPreferences.subscribeLocalNotification(event, callback)` _macOS_
|
||||
|
||||
* `event` string
|
||||
* `event` string | null
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record<string, unknown>
|
||||
@@ -122,9 +124,11 @@ Returns `number` - The ID of this subscription
|
||||
Same as `subscribeNotification`, but uses `NSNotificationCenter` for local defaults.
|
||||
This is necessary for events such as `NSUserDefaultsDidChangeNotification`.
|
||||
|
||||
If `event` is null, the `NSNotificationCenter` doesn’t use it as criteria for delivery to the observer. See [docs](https://developer.apple.com/documentation/foundation/nsnotificationcenter/1411723-addobserverforname?language=objc) for more information.
|
||||
|
||||
### `systemPreferences.subscribeWorkspaceNotification(event, callback)` _macOS_
|
||||
|
||||
* `event` string
|
||||
* `event` string | null
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record<string, unknown>
|
||||
@@ -135,6 +139,8 @@ Returns `number` - The ID of this subscription
|
||||
Same as `subscribeNotification`, but uses `NSWorkspace.sharedWorkspace.notificationCenter`.
|
||||
This is necessary for events such as `NSWorkspaceDidActivateApplicationNotification`.
|
||||
|
||||
If `event` is null, the `NSWorkspaceNotificationCenter` doesn’t use it as criteria for delivery to the observer. See [docs](https://developer.apple.com/documentation/foundation/nsnotificationcenter/1411723-addobserverforname?language=objc) for more information.
|
||||
|
||||
### `systemPreferences.unsubscribeNotification(id)` _macOS_
|
||||
|
||||
* `id` Integer
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -16,7 +16,7 @@ win.loadURL('https://twitter.com')
|
||||
|
||||
win.webContents.on(
|
||||
'did-frame-navigate',
|
||||
(event, url, isMainFrame, frameProcessId, frameRoutingId) => {
|
||||
(event, url, httpResponseCode, httpStatusText, isMainFrame, frameProcessId, frameRoutingId) => {
|
||||
const frame = webFrameMain.fromId(frameProcessId, frameRoutingId)
|
||||
if (frame) {
|
||||
const code = 'document.body.innerHTML = document.body.innerHTML.replaceAll("heck", "h*ck")'
|
||||
|
||||
@@ -110,9 +110,11 @@ webFrame.setSpellCheckProvider('en-US', {
|
||||
})
|
||||
```
|
||||
|
||||
### `webFrame.insertCSS(css)`
|
||||
#### `webFrame.insertCSS(css[, options])`
|
||||
|
||||
* `css` string - CSS source code.
|
||||
* `css` string
|
||||
* `options` Object (optional)
|
||||
* `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 `string` - A key for the inserted CSS that can later be used to remove
|
||||
the CSS via `webFrame.removeInsertedCSS(key)`.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -12,10 +12,6 @@ useful for app sub-windows that act as preference panels, or similar, as the
|
||||
parent can render to the sub-window directly, as if it were a `div` in the
|
||||
parent. This is the same behavior as in the browser.
|
||||
|
||||
When `nativeWindowOpen` is set to false, `window.open` instead results in the
|
||||
creation of a [`BrowserWindowProxy`](browser-window-proxy.md), a light wrapper
|
||||
around `BrowserWindow`.
|
||||
|
||||
Electron pairs this native Chrome `Window` with a BrowserWindow under the hood.
|
||||
You can take advantage of all the customization available when creating a
|
||||
BrowserWindow in the main process by using `webContents.setWindowOpenHandler()`
|
||||
@@ -34,7 +30,7 @@ because it is invoked in the main process.
|
||||
* `frameName` string (optional)
|
||||
* `features` string (optional)
|
||||
|
||||
Returns [`BrowserWindowProxy`](browser-window-proxy.md) | [`Window`](https://developer.mozilla.org/en-US/docs/Web/API/Window)
|
||||
Returns [`Window`](https://developer.mozilla.org/en-US/docs/Web/API/Window) | null
|
||||
|
||||
`features` is a comma-separated key-value list, following the standard format of
|
||||
the browser. Electron will parse `BrowserWindowConstructorOptions` out of this
|
||||
@@ -108,33 +104,3 @@ mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
const childWindow = window.open('', 'modal')
|
||||
childWindow.document.write('<h1>Hello</h1>')
|
||||
```
|
||||
|
||||
### `BrowserWindowProxy` example
|
||||
|
||||
```javascript
|
||||
|
||||
// main.js
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: { nativeWindowOpen: false }
|
||||
})
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
if (url.startsWith('https://github.com/')) {
|
||||
return { action: 'allow' }
|
||||
}
|
||||
return { action: 'deny' }
|
||||
})
|
||||
|
||||
mainWindow.webContents.on('did-create-window', (childWindow) => {
|
||||
// For example...
|
||||
childWindow.webContents.on('will-navigate', (e) => {
|
||||
e.preventDefault()
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
```javascript
|
||||
// renderer.js
|
||||
const windowProxy = window.open('https://github.com/', null, 'minimizable=false')
|
||||
windowProxy.postMessage('hi', '*')
|
||||
```
|
||||
|
||||
@@ -12,6 +12,44 @@ 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.
|
||||
|
||||
### Removed: `skipTaskbar` on Linux
|
||||
|
||||
On X11, `skipTaskbar` sends a `_NET_WM_STATE_SKIP_TASKBAR` message to the X11
|
||||
window manager. There is not a direct equivalent for Wayland, and the known
|
||||
workarounds have unacceptable tradeoffs (e.g. Window.is_skip_taskbar in GNOME
|
||||
requires unsafe mode), so Electron is unable to support this feature on Linux.
|
||||
|
||||
## Planned Breaking API Changes (19.0)
|
||||
|
||||
*None (yet)*
|
||||
|
||||
## Planned Breaking API Changes (18.0)
|
||||
|
||||
### Removed: `nativeWindowOpen`
|
||||
|
||||
Prior to Electron 15, `window.open` was by default shimmed to use
|
||||
`BrowserWindowProxy`. This meant that `window.open('about:blank')` did not work
|
||||
to open synchronously scriptable child windows, among other incompatibilities.
|
||||
Since Electron 15, `nativeWindowOpen` has been enabled by default.
|
||||
|
||||
See the documentation for [window.open in Electron](api/window-open.md)
|
||||
for more details.
|
||||
|
||||
## Planned Breaking API Changes (17.0)
|
||||
|
||||
### Removed: `desktopCapturer.getSources` in the renderer
|
||||
|
||||
@@ -131,7 +131,7 @@ $ gn gen out/Release --args="import(\"//electron/build/args/release.gn\")"
|
||||
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:
|
||||
|
||||
|
||||
@@ -7,21 +7,7 @@ Follow the guidelines below for building **Electron itself** on Linux, for the p
|
||||
## Prerequisites
|
||||
|
||||
* At least 25GB disk space and 8GB RAM.
|
||||
* Python 2.7.x. Some distributions like CentOS 6.x still use Python 2.6.x
|
||||
so you may need to check your Python version with `python -V`.
|
||||
|
||||
Please also ensure that your system and Python version support at least TLS 1.2.
|
||||
For a quick test, run the following script:
|
||||
|
||||
```sh
|
||||
$ npx @electron/check-python-tls
|
||||
```
|
||||
|
||||
If the script returns that your configuration is using an outdated security
|
||||
protocol, use your system's package manager to update Python to the latest
|
||||
version in the 2.7.x branch. Alternatively, visit https://www.python.org/downloads/
|
||||
for detailed instructions.
|
||||
|
||||
* Python >= 3.7.
|
||||
* Node.js. There are various ways to install Node. You can download
|
||||
source code from [nodejs.org](https://nodejs.org) and compile it.
|
||||
Doing so permits installing Node on your own home directory as a standard user.
|
||||
@@ -29,7 +15,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 \
|
||||
|
||||
@@ -6,45 +6,12 @@ Follow the guidelines below for building **Electron itself** on macOS, for the p
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* macOS >= 10.11.6
|
||||
* [Xcode](https://developer.apple.com/technologies/tools/) >= 9.0.0
|
||||
* macOS >= 11.6.0
|
||||
* [Xcode](https://developer.apple.com/technologies/tools/). The exact version
|
||||
needed depends on what branch you are building, but the latest version of
|
||||
Xcode is generally a good bet for building `main`.
|
||||
* [node.js](https://nodejs.org) (external)
|
||||
* Python 2.7 with support for TLS 1.2
|
||||
|
||||
## Python
|
||||
|
||||
Please also ensure that your system and Python version support at least TLS 1.2.
|
||||
This depends on both your version of macOS and Python. For a quick test, run:
|
||||
|
||||
```sh
|
||||
$ npx @electron/check-python-tls
|
||||
```
|
||||
|
||||
If the script returns that your configuration is using an outdated security
|
||||
protocol, you can either update macOS to High Sierra or install a new version
|
||||
of Python 2.7.x. To upgrade Python, use [Homebrew](https://brew.sh/):
|
||||
|
||||
```sh
|
||||
$ brew install python@2 && brew link python@2 --force
|
||||
```
|
||||
|
||||
If you are using Python as provided by Homebrew, you also need to install
|
||||
the following Python modules:
|
||||
|
||||
* [pyobjc](https://pypi.org/project/pyobjc/#description)
|
||||
|
||||
You can use `pip` to install it:
|
||||
|
||||
```sh
|
||||
$ pip install pyobjc
|
||||
```
|
||||
|
||||
## macOS SDK
|
||||
|
||||
If you're developing Electron and don't plan to redistribute your
|
||||
custom Electron build, you may skip this section.
|
||||
|
||||
Official Electron builds are built with [Xcode 12.2](https://download.developer.apple.com/Developer_Tools/Xcode_12.2/Xcode_12.2.xip), and the macOS 11.0 SDK. Building with a newer SDK works too, but the releases currently use the 11.0 SDK.
|
||||
* Python >= 3.7
|
||||
|
||||
## Building Electron
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ For C++ and Python, we follow Chromium's [Coding
|
||||
Style](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/styleguide.md).
|
||||
There is also a script `script/cpplint.py` to check whether all files conform.
|
||||
|
||||
The Python version we are using now is Python 2.7.
|
||||
The Python version we are using now is Python 3.9.
|
||||
|
||||
The C++ code uses a lot of Chromium's abstractions and types, so it's
|
||||
recommended to get acquainted with them. A good place to start is
|
||||
|
||||
@@ -35,6 +35,28 @@ base::debug::StackTrace().Print();
|
||||
|
||||
This will allow you to observe call chains and identify potential issue areas.
|
||||
|
||||
## Breakpoint Debugging
|
||||
|
||||
> Note that this will increase the size of the build significantly, taking up around 50G of disk space
|
||||
|
||||
Write the following file to `electron/.git/info/exclude/debug.gn`
|
||||
|
||||
```gn
|
||||
import("//electron/build/args/testing.gn")
|
||||
is_debug = true
|
||||
symbol_level = 2
|
||||
forbid_non_component_debug_builds = false
|
||||
```
|
||||
|
||||
Then execute:
|
||||
|
||||
```sh
|
||||
$ gn gen out/Debug --args="import(\"//electron/.git/info/exclude/debug.gn\") $GN_EXTRA_ARGS"
|
||||
$ ninja -C out/Debug electron
|
||||
```
|
||||
|
||||
Now you can use `LLDB` for breakpoint debugging.
|
||||
|
||||
## Platform-Specific Debugging
|
||||
<!-- TODO(@codebytere): add debugging file for Linux-->
|
||||
|
||||
|
||||
0
docs/fiddles/communication/two-processes/.keep
Normal file
0
docs/fiddles/communication/two-processes/.keep
Normal file
@@ -0,0 +1,27 @@
|
||||
<!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>
|
||||
@@ -0,0 +1,29 @@
|
||||
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')
|
||||
})
|
||||
@@ -0,0 +1,12 @@
|
||||
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
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
<!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>
|
||||
@@ -0,0 +1,29 @@
|
||||
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'
|
||||
})
|
||||
@@ -0,0 +1,9 @@
|
||||
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
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
const {app, BrowserWindow, ipcMain,dialog} = require('electron')
|
||||
const {app, BrowserWindow, ipcMain, dialog} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
async function handleFileOpen() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const {app, BrowserWindow, Menu} = require('electron')
|
||||
const {app, BrowserWindow, Menu, ipcMain} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
|
||||
@@ -4,5 +4,5 @@ window.electronAPI.handleCounter((event, value) => {
|
||||
const oldValue = Number(counter.innerText)
|
||||
const newValue = oldValue + value
|
||||
counter.innerText = newValue
|
||||
event.reply('counter-value', newValue)
|
||||
event.sender.send('counter-value', newValue)
|
||||
})
|
||||
|
||||
21
docs/fiddles/tutorial-first-app/index.html
Normal file
21
docs/fiddles/tutorial-first-app/index.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<meta
|
||||
http-equiv="X-Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<title>Hello from Electron renderer!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello from Electron renderer!</h1>
|
||||
<p>👋</p>
|
||||
<p id="info"></p>
|
||||
</body>
|
||||
<script src="./renderer.js"></script>
|
||||
</html>
|
||||
26
docs/fiddles/tutorial-first-app/main.js
Normal file
26
docs/fiddles/tutorial-first-app/main.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const { app, BrowserWindow } = require('electron');
|
||||
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
});
|
||||
|
||||
win.loadFile('index.html');
|
||||
};
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow();
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
21
docs/fiddles/tutorial-preload/index.html
Normal file
21
docs/fiddles/tutorial-preload/index.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<meta
|
||||
http-equiv="X-Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<title>Hello from Electron renderer!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello from Electron renderer!</h1>
|
||||
<p>👋</p>
|
||||
<p id="info"></p>
|
||||
</body>
|
||||
<script src="./renderer.js"></script>
|
||||
</html>
|
||||
30
docs/fiddles/tutorial-preload/main.js
Normal file
30
docs/fiddles/tutorial-preload/main.js
Normal file
@@ -0,0 +1,30 @@
|
||||
const { app, BrowserWindow } = require('electron');
|
||||
const path = require('path');
|
||||
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
},
|
||||
});
|
||||
|
||||
win.loadFile('index.html');
|
||||
};
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow();
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
7
docs/fiddles/tutorial-preload/preload.js
Normal file
7
docs/fiddles/tutorial-preload/preload.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const { contextBridge } = require('electron');
|
||||
|
||||
contextBridge.exposeInMainWorld('versions', {
|
||||
node: () => process.versions.node,
|
||||
chrome: () => process.versions.chrome,
|
||||
electron: () => process.versions.electron,
|
||||
});
|
||||
2
docs/fiddles/tutorial-preload/renderer.js
Normal file
2
docs/fiddles/tutorial-preload/renderer.js
Normal file
@@ -0,0 +1,2 @@
|
||||
const information = document.getElementById('info');
|
||||
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`;
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 190 KiB After Width: | Height: | Size: 59 KiB |
BIN
docs/images/preload-example.png
Normal file
BIN
docs/images/preload-example.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
docs/images/windows-taskbar-icon-overlay.png
Normal file
BIN
docs/images/windows-taskbar-icon-overlay.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
docs/images/windows-taskbar-jumplist.png
Normal file
BIN
docs/images/windows-taskbar-jumplist.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 173 KiB |
BIN
docs/images/windows-taskbar-thumbnail-toolbar.png
Normal file
BIN
docs/images/windows-taskbar-thumbnail-toolbar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 142 KiB |
@@ -1,26 +1,26 @@
|
||||
# Application Distribution
|
||||
---
|
||||
title: 'Application Packaging'
|
||||
description: 'To distribute your app with Electron, you need to package and rebrand it. To do this, you can either use specialized tooling or manual approaches.'
|
||||
slug: application-distribution
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
To distribute your app with Electron, you need to package and rebrand it.
|
||||
To do this, you can either use specialized tooling or manual approaches.
|
||||
To distribute your app with Electron, you need to package and rebrand it. To do this, you
|
||||
can either use specialized tooling or manual approaches.
|
||||
|
||||
## With tooling
|
||||
|
||||
You can use the following tools to distribute your application:
|
||||
There are a couple tools out there that exist to package and distribute your Electron app.
|
||||
We recommend using [Electron Forge](https://www.electronforge.io). You can check out
|
||||
its documentation directly, or refer to the [Packaging and Distribution](./tutorial-5-packaging.md)
|
||||
part of the Electron tutorial.
|
||||
|
||||
* [electron-forge](https://github.com/electron-userland/electron-forge)
|
||||
* [electron-builder](https://github.com/electron-userland/electron-builder)
|
||||
* [electron-packager](https://github.com/electron/electron-packager)
|
||||
## Manual packaging
|
||||
|
||||
These tools will take care of all the steps you need to take to end up with a
|
||||
distributable Electron application, such as bundling your application,
|
||||
rebranding the executable, and setting the right icons.
|
||||
If you prefer the manual approach, there are 2 ways to distribute your application:
|
||||
|
||||
You can check the example of how to package your app with `electron-forge` in
|
||||
the [Quick Start guide](quick-start.md#package-and-distribute-your-application).
|
||||
|
||||
## Manual distribution
|
||||
- With prebuilt binaries
|
||||
- With an app source code archive
|
||||
|
||||
### With prebuilt binaries
|
||||
|
||||
@@ -29,21 +29,19 @@ binaries](https://github.com/electron/electron/releases). Next, the folder
|
||||
containing your app should be named `app` and placed in Electron's resources
|
||||
directory as shown in the following examples.
|
||||
|
||||
> *NOTE:* the location of Electron's prebuilt binaries is indicated
|
||||
:::note
|
||||
The location of Electron's prebuilt binaries is indicated
|
||||
with `electron/` in the examples below.
|
||||
:::
|
||||
|
||||
*On macOS:*
|
||||
|
||||
```plaintext
|
||||
```plain title='macOS'
|
||||
electron/Electron.app/Contents/Resources/app/
|
||||
├── package.json
|
||||
├── main.js
|
||||
└── index.html
|
||||
```
|
||||
|
||||
*On Windows and Linux:*
|
||||
|
||||
```plaintext
|
||||
```plain title='Windows and Linux'
|
||||
electron/resources/app
|
||||
├── package.json
|
||||
├── main.js
|
||||
@@ -54,7 +52,7 @@ Then execute `Electron.app` on macOS, `electron` on Linux, or `electron.exe`
|
||||
on Windows, and Electron will start as your app. The `electron` directory
|
||||
will then be your distribution to deliver to users.
|
||||
|
||||
### With an app source code archive
|
||||
### With an app source code archive (asar)
|
||||
|
||||
Instead of shipping your app by copying all of its source files, you can
|
||||
package your app into an [asar] archive to improve the performance of reading
|
||||
@@ -65,16 +63,12 @@ To use an `asar` archive to replace the `app` folder, you need to rename the
|
||||
archive to `app.asar`, and put it under Electron's resources directory like
|
||||
below, and Electron will then try to read the archive and start from it.
|
||||
|
||||
*On macOS:*
|
||||
|
||||
```plaintext
|
||||
```plain title='macOS'
|
||||
electron/Electron.app/Contents/Resources/
|
||||
└── app.asar
|
||||
```
|
||||
|
||||
*On Windows and Linux:*
|
||||
|
||||
```plaintext
|
||||
```plain title='Windows'
|
||||
electron/resources/
|
||||
└── app.asar
|
||||
```
|
||||
@@ -87,47 +81,44 @@ You can find more details on how to use `asar` in the
|
||||
After bundling your app into Electron, you will want to rebrand Electron
|
||||
before distributing it to users.
|
||||
|
||||
#### macOS
|
||||
- **Windows:** You can rename `electron.exe` to any name you like, and edit
|
||||
its icon and other information with tools like [rcedit](https://github.com/electron/rcedit).
|
||||
- **Linux:** You can rename the `electron` executable to any name you like.
|
||||
- **macOS:** You can rename `Electron.app` to any name you want, and you also have to rename
|
||||
the `CFBundleDisplayName`, `CFBundleIdentifier` and `CFBundleName` fields in the
|
||||
following files:
|
||||
|
||||
You can rename `Electron.app` to any name you want, and you also have to rename
|
||||
the `CFBundleDisplayName`, `CFBundleIdentifier` and `CFBundleName` fields in the
|
||||
following files:
|
||||
- `Electron.app/Contents/Info.plist`
|
||||
- `Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist`
|
||||
|
||||
* `Electron.app/Contents/Info.plist`
|
||||
* `Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist`
|
||||
You can also rename the helper app to avoid showing `Electron Helper` in the
|
||||
Activity Monitor, but make sure you have renamed the helper app's executable
|
||||
file's name.
|
||||
|
||||
You can also rename the helper app to avoid showing `Electron Helper` in the
|
||||
Activity Monitor, but make sure you have renamed the helper app's executable
|
||||
file's name.
|
||||
The structure of a renamed app would be like:
|
||||
|
||||
The structure of a renamed app would be like:
|
||||
|
||||
```plaintext
|
||||
```plain
|
||||
MyApp.app/Contents
|
||||
├── Info.plist
|
||||
├── MacOS/
|
||||
│ └── MyApp
|
||||
│ └── MyApp
|
||||
└── Frameworks/
|
||||
└── MyApp Helper.app
|
||||
├── Info.plist
|
||||
└── MacOS/
|
||||
└── MyApp Helper
|
||||
└── MyApp Helper
|
||||
```
|
||||
|
||||
#### Windows
|
||||
:::note
|
||||
|
||||
You can rename `electron.exe` to any name you like, and edit its icon and other
|
||||
information with tools like [rcedit](https://github.com/electron/rcedit).
|
||||
|
||||
#### Linux
|
||||
|
||||
You can rename the `electron` executable to any name you like.
|
||||
|
||||
### Rebranding by rebuilding Electron from source
|
||||
|
||||
It is also possible to rebrand Electron by changing the product name and
|
||||
it is also possible to rebrand Electron by changing the product name and
|
||||
building it from source. To do this you need to set the build argument
|
||||
corresponding to the product name (`electron_product_name = "YourProductName"`)
|
||||
in the `args.gn` file and rebuild.
|
||||
|
||||
Keep in mind this is not recommended as setting up the environment to compile
|
||||
from source is not trivial and takes significant time.
|
||||
|
||||
:::
|
||||
|
||||
[asar]: https://github.com/electron/asar
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
# Code Signing
|
||||
---
|
||||
title: 'Code Signing'
|
||||
description: 'Code signing is a security technology that you use to certify that an app was created by you.'
|
||||
slug: code-signing
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
Code signing is a security technology that you use to certify that an app was
|
||||
created by you.
|
||||
created by you. You should sign your application so it does not trigger any
|
||||
operating system security checks.
|
||||
|
||||
On macOS the system can detect any change to the app, whether the change is
|
||||
On macOS, the system can detect any change to the app, whether the change is
|
||||
introduced accidentally or by malicious code.
|
||||
|
||||
On Windows, the system assigns a trust level to your code signing certificate
|
||||
which if you don't have, or if your trust level is low, will cause security
|
||||
dialogs to appear when users start using your application. Trust level builds
|
||||
dialogs to appear when users start using your application. Trust level builds
|
||||
over time so it's better to start code signing as early as possible.
|
||||
|
||||
While it is possible to distribute unsigned apps, it is not recommended. Both
|
||||
@@ -16,20 +22,19 @@ Windows and macOS will, by default, prevent either the download or the execution
|
||||
of unsigned applications. Starting with macOS Catalina (version 10.15), users
|
||||
have to go through multiple manual steps to open unsigned applications.
|
||||
|
||||

|
||||

|
||||
|
||||
As you can see, users get two options: Move the app straight to the trash or
|
||||
cancel running it. You don't want your users to see that dialog.
|
||||
|
||||
If you are building an Electron app that you intend to package and distribute,
|
||||
it should be code-signed.
|
||||
it should be code signed.
|
||||
|
||||
# Signing & notarizing macOS builds
|
||||
## Signing & notarizing macOS builds
|
||||
|
||||
Properly preparing macOS applications for release requires two steps: First, the
|
||||
app needs to be code-signed. Then, the app needs to be uploaded to Apple for a
|
||||
process called "notarization", where automated systems will further verify that
|
||||
Properly preparing macOS applications for release requires two steps. First, the
|
||||
app needs to be code signed. Then, the app needs to be uploaded to Apple for a
|
||||
process called **notarization**, where automated systems will further verify that
|
||||
your app isn't doing anything to endanger its users.
|
||||
|
||||
To start the process, ensure that you fulfill the requirements for signing and
|
||||
@@ -42,18 +47,18 @@ notarizing your app:
|
||||
Electron's ecosystem favors configuration and freedom, so there are multiple
|
||||
ways to get your application signed and notarized.
|
||||
|
||||
## `electron-forge`
|
||||
### Using Electron Forge
|
||||
|
||||
If you're using Electron's favorite build tool, getting your application signed
|
||||
and notarized requires a few additions to your configuration. [Forge](https://electronforge.io) is a
|
||||
collection of the official Electron tools, using [`electron-packager`],
|
||||
[`electron-osx-sign`], and [`electron-notarize`] under the hood.
|
||||
|
||||
Let's take a look at an example configuration with all required fields. Not all
|
||||
of them are required: the tools will be clever enough to automatically find a
|
||||
suitable `identity`, for instance, but we recommend that you are explicit.
|
||||
Let's take a look at an example `package.json` configuration with all required fields. Not all of them are
|
||||
required: the tools will be clever enough to automatically find a suitable `identity`, for instance,
|
||||
but we recommend that you are explicit.
|
||||
|
||||
```json
|
||||
```json title="package.json" {7}
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "0.0.1",
|
||||
@@ -69,7 +74,7 @@ suitable `identity`, for instance, but we recommend that you are explicit.
|
||||
},
|
||||
"osxNotarize": {
|
||||
"appleId": "felix@felix.fun",
|
||||
"appleIdPassword": "my-apple-id-password",
|
||||
"appleIdPassword": "my-apple-id-password"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,11 +82,11 @@ suitable `identity`, for instance, but we recommend that you are explicit.
|
||||
}
|
||||
```
|
||||
|
||||
The `plist` file referenced here needs the following macOS-specific entitlements
|
||||
The `entitlements.plist` file referenced here needs the following macOS-specific entitlements
|
||||
to assure the Apple security mechanisms that your app is doing these things
|
||||
without meaning any harm:
|
||||
|
||||
```xml
|
||||
```xml title="entitlements.plist"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
@@ -104,7 +109,7 @@ file](https://github.com/electron/fiddle/blob/master/forge.config.js).
|
||||
If you plan to access the microphone or camera within your app using Electron's APIs, you'll also
|
||||
need to add the following entitlements:
|
||||
|
||||
```xml
|
||||
```xml title="entitlements.plist"
|
||||
<key>com.apple.security.device.audio-input</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.camera</key>
|
||||
@@ -113,28 +118,26 @@ need to add the following entitlements:
|
||||
|
||||
If these are not present in your app's entitlements when you invoke, for example:
|
||||
|
||||
```js
|
||||
```js title="main.js"
|
||||
const { systemPreferences } = require('electron')
|
||||
|
||||
const microphone = systemPreferences.askForMediaAccess('microphone')
|
||||
```
|
||||
|
||||
Your app may crash. See the Resource Access section in [Hardened Runtime](https://developer.apple.com/documentation/security/hardened_runtime) for more information and entitlements you may need.
|
||||
|
||||
## `electron-builder`
|
||||
### Using Electron Builder
|
||||
|
||||
Electron Builder comes with a custom solution for signing your application. You
|
||||
can find [its documentation here](https://www.electron.build/code-signing).
|
||||
|
||||
## `electron-packager`
|
||||
### Using Electron Packager
|
||||
|
||||
If you're not using an integrated build pipeline like Forge or Builder, you
|
||||
are likely using [`electron-packager`], which includes [`electron-osx-sign`] and
|
||||
[`electron-notarize`].
|
||||
|
||||
If you're using Packager's API, you can pass [in configuration that both signs
|
||||
and notarizes your
|
||||
application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html).
|
||||
and notarizes your application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html).
|
||||
|
||||
```js
|
||||
const packager = require('electron-packager')
|
||||
@@ -155,11 +158,11 @@ packager({
|
||||
})
|
||||
```
|
||||
|
||||
The `plist` file referenced here needs the following macOS-specific entitlements
|
||||
The `entitlements.plist` file referenced here needs the following macOS-specific entitlements
|
||||
to assure the Apple security mechanisms that your app is doing these things
|
||||
without meaning any harm:
|
||||
|
||||
```xml
|
||||
```xml title="entitlements.plist"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
@@ -175,11 +178,11 @@ without meaning any harm:
|
||||
Up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
|
||||
as well. However, it should not be used anymore if it can be avoided.
|
||||
|
||||
## Mac App Store
|
||||
### Signing Mac App Store applications
|
||||
|
||||
See the [Mac App Store Guide].
|
||||
|
||||
# Signing Windows builds
|
||||
## Signing Windows builds
|
||||
|
||||
Before signing Windows builds, you must do the following:
|
||||
|
||||
@@ -190,31 +193,140 @@ Before signing Windows builds, you must do the following:
|
||||
You can get a code signing certificate from a lot of resellers. Prices vary, so
|
||||
it may be worth your time to shop around. Popular resellers include:
|
||||
|
||||
* [digicert](https://www.digicert.com/code-signing/microsoft-authenticode.htm)
|
||||
* [Sectigo](https://sectigo.com/ssl-certificates-tls/code-signing)
|
||||
* Amongst others, please shop around to find one that suits your needs, Google
|
||||
is your friend 😄
|
||||
- [digicert](https://www.digicert.com/code-signing/microsoft-authenticode.htm)
|
||||
- [Sectigo](https://sectigo.com/ssl-certificates-tls/code-signing)
|
||||
- Amongst others, please shop around to find one that suits your needs! 😄
|
||||
|
||||
There are a number of tools for signing your packaged app:
|
||||
:::caution Keep your certificate password private
|
||||
Your certificate password should be a **secret**. Do not share it publicly or
|
||||
commit it to your source code.
|
||||
:::
|
||||
|
||||
* [`electron-winstaller`] will generate an installer for windows and sign it for
|
||||
you
|
||||
* [`electron-forge`] can sign installers it generates through the
|
||||
Squirrel.Windows or MSI targets.
|
||||
* [`electron-builder`] can sign some of its windows targets
|
||||
### Using Electron Forge
|
||||
|
||||
## Windows Store
|
||||
Once you have a code signing certificate file (`.pfx`), you can sign
|
||||
[Squirrel.Windows][maker-squirrel] and [MSI][maker-msi] installers in Electron Forge
|
||||
with the `certificateFile` and `certificatePassword` fields in their respective
|
||||
configuration objects.
|
||||
|
||||
For example, if you keep your Forge config in your `package.json` file and are
|
||||
creating a Squirrel.Windows installer:
|
||||
|
||||
```json {9-15} title='package.json'
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "0.0.1",
|
||||
//...
|
||||
"config": {
|
||||
"forge": {
|
||||
"packagerConfig": {},
|
||||
"makers": [
|
||||
{
|
||||
"name": "@electron-forge/maker-squirrel",
|
||||
"config": {
|
||||
"certificateFile": "./cert.pfx",
|
||||
"certificatePassword": "this-is-a-secret"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
### Using electron-winstaller (Squirrel.Windows)
|
||||
|
||||
[`electron-winstaller`] is a package that can generate Squirrel.Windows installers for your
|
||||
Electron app. This is the tool used under the hood by Electron Forge's
|
||||
[Squirrel.Windows Maker][maker-squirrel]. If you're not using Electron Forge and want to use
|
||||
`electron-winstaller` directly, use the `certificateFile` and `certificatePassword` configuration
|
||||
options when creating your installer.
|
||||
|
||||
```js {10-11}
|
||||
const electronInstaller = require('electron-winstaller')
|
||||
// NB: Use this syntax within an async function, Node does not have support for
|
||||
// top-level await as of Node 12.
|
||||
try {
|
||||
await electronInstaller.createWindowsInstaller({
|
||||
appDirectory: '/tmp/build/my-app-64',
|
||||
outputDirectory: '/tmp/build/installer64',
|
||||
authors: 'My App Inc.',
|
||||
exe: 'myapp.exe',
|
||||
certificateFile: './cert.pfx',
|
||||
certificatePassword: 'this-is-a-secret',
|
||||
})
|
||||
console.log('It worked!')
|
||||
} catch (e) {
|
||||
console.log(`No dice: ${e.message}`)
|
||||
}
|
||||
```
|
||||
|
||||
For full configuration options, check out the [`electron-winstaller`] repository!
|
||||
|
||||
### Using electron-wix-msi (WiX MSI)
|
||||
|
||||
[`electron-wix-msi`] is a package that can generate MSI installers for your
|
||||
Electron app. This is the tool used under the hood by Electron Forge's [MSI Maker][maker-msi].
|
||||
|
||||
If you're not using Electron Forge and want to use `electron-wix-msi` directly, use the
|
||||
`certificateFile` and `certificatePassword` configuration options
|
||||
or pass in parameters directly to [SignTool.exe] with the `signWithParams` option.
|
||||
|
||||
```js {12-13}
|
||||
import { MSICreator } from 'electron-wix-msi'
|
||||
|
||||
// Step 1: Instantiate the MSICreator
|
||||
const msiCreator = new MSICreator({
|
||||
appDirectory: '/path/to/built/app',
|
||||
description: 'My amazing Kitten simulator',
|
||||
exe: 'kittens',
|
||||
name: 'Kittens',
|
||||
manufacturer: 'Kitten Technologies',
|
||||
version: '1.1.2',
|
||||
outputDirectory: '/path/to/output/folder',
|
||||
certificateFile: './cert.pfx',
|
||||
certificatePassword: 'this-is-a-secret',
|
||||
})
|
||||
|
||||
// Step 2: Create a .wxs template file
|
||||
const supportBinaries = await msiCreator.create()
|
||||
|
||||
// 🆕 Step 2a: optionally sign support binaries if you
|
||||
// sign you binaries as part of of your packaging script
|
||||
supportBinaries.forEach(async (binary) => {
|
||||
// Binaries are the new stub executable and optionally
|
||||
// the Squirrel auto updater.
|
||||
await signFile(binary)
|
||||
})
|
||||
|
||||
// Step 3: Compile the template to a .msi file
|
||||
await msiCreator.compile()
|
||||
```
|
||||
|
||||
For full configuration options, check out the [`electron-wix-msi`] repository!
|
||||
|
||||
### Using Electron Builder
|
||||
|
||||
Electron Builder comes with a custom solution for signing your application. You
|
||||
can find [its documentation here](https://www.electron.build/code-signing).
|
||||
|
||||
### Signing Windows Store applications
|
||||
|
||||
See the [Windows Store Guide].
|
||||
|
||||
[Apple Developer Program]: https://developer.apple.com/programs/
|
||||
[apple developer program]: https://developer.apple.com/programs/
|
||||
[`electron-builder`]: https://github.com/electron-userland/electron-builder
|
||||
[`electron-forge`]: https://github.com/electron-userland/electron-forge
|
||||
[`electron-osx-sign`]: https://github.com/electron-userland/electron-osx-sign
|
||||
[`electron-packager`]: https://github.com/electron/electron-packager
|
||||
[`electron-notarize`]: https://github.com/electron/electron-notarize
|
||||
[`electron-winstaller`]: https://github.com/electron/windows-installer
|
||||
[Xcode]: https://developer.apple.com/xcode
|
||||
[`electron-wix-msi`]: https://github.com/felixrieseberg/electron-wix-msi
|
||||
[xcode]: https://developer.apple.com/xcode
|
||||
[signing certificates]: https://github.com/electron/electron-osx-sign/wiki/1.-Getting-Started#certificates
|
||||
[Mac App Store Guide]: mac-app-store-submission-guide.md
|
||||
[Windows Store Guide]: windows-store-guide.md
|
||||
[mac app store guide]: ./mac-app-store-submission-guide.md
|
||||
[windows store guide]: ./windows-store-guide.md
|
||||
[maker-squirrel]: https://www.electronforge.io/config/makers/squirrel.windows
|
||||
[maker-msi]: https://www.electronforge.io/config/makers/wix-msi
|
||||
[signtool.exe]: https://docs.microsoft.com/en-us/dotnet/framework/tools/signtool-exe
|
||||
|
||||
54
docs/tutorial/distribution-overview.md
Normal file
54
docs/tutorial/distribution-overview.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: 'Distribution Overview'
|
||||
description: 'To distribute your app with Electron, you need to package and rebrand it. To do this, you can either use specialized tooling or manual approaches.'
|
||||
slug: distribution-overview
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
Once your app is ready for production, there are a couple steps you need to take before
|
||||
you can deliver it to your users.
|
||||
|
||||
## Packaging
|
||||
|
||||
To distribute your app with Electron, you need to package all your resources and assets
|
||||
into an executable and rebrand it. To do this, you can either use specialized tooling
|
||||
or do it manually. See the [Application Packaging][application-packaging] tutorial
|
||||
for more information.
|
||||
|
||||
## Code signing
|
||||
|
||||
Code signing is a security technology that you use to certify that an app was
|
||||
created by you. You should sign your application so it does not trigger the
|
||||
security checks of your user's operating system.
|
||||
|
||||
To get started with each operating system's code signing process, please read the
|
||||
[Code Signing][code-signing] docs.
|
||||
|
||||
## Publishing
|
||||
|
||||
Once your app is packaged and signed, you can freely distribute your app directly
|
||||
to users by uploading your installers online.
|
||||
|
||||
To reach more users, you can also choose to upload your app to each operating system's
|
||||
digital distribution platform (i.e. app store). These require another build step aside
|
||||
from your direct download app. For more information, check out each individual app store guide:
|
||||
|
||||
- [Mac App Store][mac-app]
|
||||
- [Windows Store][windows-store]
|
||||
- [Snapcraft (Linux)][snapcraft]
|
||||
|
||||
## Updating
|
||||
|
||||
Electron's auto-updater allows you to deliver application updates to users
|
||||
without forcing them to manually download new versions of your application.
|
||||
Check out the [Updating Applications][updates] guide for details on implementing automatic updates
|
||||
with Electron.
|
||||
|
||||
<!-- Link labels -->
|
||||
|
||||
[application-packaging]: ./application-distribution.md
|
||||
[code-signing]: ./code-signing.md
|
||||
[mac-app]: ./mac-app-store-submission-guide.md
|
||||
[windows-store]: ./windows-store-guide.md
|
||||
[snapcraft]: ./snapcraft.md
|
||||
[updates]: ./updates.md
|
||||
56
docs/tutorial/examples.md
Normal file
56
docs/tutorial/examples.md
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
title: 'Examples Overview'
|
||||
description: 'A set of examples for common Electron features'
|
||||
slug: examples
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
# Examples Overview
|
||||
|
||||
In this section, we have collected a set of guides for common features
|
||||
that you may want to implement in your Electron application. Each guide
|
||||
contains a practical example in a minimal, self-contained example app.
|
||||
The easiest way to run these examples is by downloading [Electron Fiddle][fiddle].
|
||||
|
||||
Once Fiddle is installed, you can press on the "Open in Fiddle" button that you
|
||||
will find below code samples like the following one:
|
||||
|
||||
```fiddle docs/fiddles/quick-start
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const replaceText = (selector, text) => {
|
||||
const element = document.getElementById(selector)
|
||||
if (element) element.innerText = text
|
||||
}
|
||||
|
||||
for (const type of ['chrome', 'node', 'electron']) {
|
||||
replaceText(`${type}-version`, process.versions[type])
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
If there is still something that you do not know how to do, please take a look at the [API][app]
|
||||
as there is a chance it might be documented just there (and also open an issue requesting the
|
||||
guide!).
|
||||
|
||||
<!-- guide-table-start -->
|
||||
|
||||
| Guide | Description |
|
||||
| :-------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Message ports] | This guide provides some examples of how you might use MessagePorts in your app to communicate different processes. |
|
||||
| [Device access] | Learn how to access the device hardware (Bluetooth, USB, Serial). |
|
||||
| [Keyboard shortcuts] | Configure local and global keyboard shortcuts for your Electron application. |
|
||||
| [Multithreading] | With Web Workers, it is possible to run JavaScript in OS-level threads |
|
||||
| [Offscreen rendering] | Offscreen rendering lets you obtain the content of a BrowserWindow in a bitmap, so it can be rendered anywhere. |
|
||||
| [Spellchecker] | Learn how to use the built-in spellchecker, set languages, etc. |
|
||||
| [Web embeds] | Discover the different ways to embed third-party web content in your application. |
|
||||
|
||||
<!-- guide-table-end -->
|
||||
|
||||
## How to...?
|
||||
|
||||
You can find the full list of "How to?" in the sidebar. If there is
|
||||
something that you would like to do that is not documented, please join
|
||||
our [Discord server][] and let us know!
|
||||
|
||||
[discord server]: https://discord.com/invite/electron
|
||||
[fiddle]: https://www.electronjs.org/fiddle
|
||||
@@ -73,7 +73,7 @@ url = ELECTRON_MIRROR + ELECTRON_CUSTOM_DIR + '/' + ELECTRON_CUSTOM_FILENAME
|
||||
For instance, to use the China CDN mirror:
|
||||
|
||||
```shell
|
||||
ELECTRON_MIRROR="https://cdn.npm.taobao.org/dist/electron/"
|
||||
ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
|
||||
```
|
||||
|
||||
By default, `ELECTRON_CUSTOM_DIR` is set to `v$VERSION`. To change the format,
|
||||
@@ -83,12 +83,12 @@ resolves to `version-5.0.0`, `{{ version }}` resolves to `5.0.0`, and
|
||||
use the China non-CDN mirror:
|
||||
|
||||
```shell
|
||||
ELECTRON_MIRROR="https://npm.taobao.org/mirrors/electron/"
|
||||
ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
|
||||
ELECTRON_CUSTOM_DIR="{{ version }}"
|
||||
```
|
||||
|
||||
The above configuration will download from URLs such as
|
||||
`https://npm.taobao.org/mirrors/electron/8.0.0/electron-v8.0.0-linux-x64.zip`.
|
||||
`https://npmmirror.com/mirrors/electron/8.0.0/electron-v8.0.0-linux-x64.zip`.
|
||||
|
||||
If your mirror serves artifacts with different checksums to the official
|
||||
Electron release you may have to set `electron_use_remote_checksums=1` to
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# Introduction
|
||||
---
|
||||
title: 'Introduction'
|
||||
description: 'Welcome to the Electron documentation! If this is your first time developing an Electron app, read through this Getting Started section to get familiar with the basics. Otherwise, feel free to explore our guides and API documentation!'
|
||||
slug: /latest/
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
Welcome to the Electron documentation! If this is your first time developing
|
||||
an Electron app, read through this Getting Started section to get familiar with the
|
||||
basics. Otherwise, feel free to explore our guides and API documentation!
|
||||
|
||||
## What is Electron?
|
||||
# What is Electron?
|
||||
|
||||
Electron is a framework for building desktop applications using JavaScript,
|
||||
HTML, and CSS. By embedding [Chromium][chromium] and [Node.js][node] into its
|
||||
@@ -12,20 +13,12 @@ binary, Electron allows you to maintain one JavaScript codebase and create
|
||||
cross-platform apps that work on Windows, macOS, and Linux — no native development
|
||||
experience required.
|
||||
|
||||
## Prerequisites
|
||||
## Getting started
|
||||
|
||||
These docs operate under the assumption that the reader is familiar with both
|
||||
Node.js and general web development. If you need to get more comfortable with
|
||||
either of these areas, we recommend the following resources:
|
||||
|
||||
* [Getting started with the Web (MDN)][mdn-guide]
|
||||
* [Introduction to Node.js][node-guide]
|
||||
|
||||
Moreover, you'll have a better time understanding how Electron works if you get
|
||||
acquainted with Chromium's process model. You can get a brief overview of
|
||||
Chrome architecture with the [Chrome comic][comic], which was released alongside
|
||||
Chrome's launch back in 2008. Although it's been over a decade since then, the
|
||||
core principles introduced in the comic remain helpful to understand Electron.
|
||||
We recommend you to start with the [tutorial], which guides you through the
|
||||
process of developing an Electron app and distributing it to users.
|
||||
The [examples] and [API documentation] are also good places to browse around
|
||||
and discover new things.
|
||||
|
||||
## Running examples with Electron Fiddle
|
||||
|
||||
@@ -39,21 +32,44 @@ a code block. If you have Fiddle installed, this button will open a
|
||||
`fiddle.electronjs.org` link that will automatically load the example into Fiddle,
|
||||
no copy-pasting required.
|
||||
|
||||
```fiddle docs/fiddles/quick-start
|
||||
```
|
||||
|
||||
## What is in the docs?
|
||||
|
||||
All the official documentation is available from the sidebar. These
|
||||
are the different categories and what you can expect on each one:
|
||||
|
||||
- **Tutorial**: An end-to-end guide on how to create and publish your first Electron
|
||||
application.
|
||||
- **Processes in Electron**: In-depth reference on Electron processes and how to work with them.
|
||||
- **Best Practices**: Important checklists to keep in mind when developing an Electron app.
|
||||
- **How-To Examples**: Quick references to add features to your Electron app.
|
||||
- **Development**: Miscellaneous development guides.
|
||||
- **Distribution**: Learn how to distribute your app to end users.
|
||||
- **Testing and debugging**: How to debug JavaScript, write tests, and other tools used
|
||||
to create quality Electron applications.
|
||||
- **Resources**: Useful links to better understand how the Electron project works
|
||||
and is organized.
|
||||
- **Contributing to Electron**: Compiling Electron and making contributions can be daunting.
|
||||
We try to make it easier in this section.
|
||||
|
||||
## Getting help
|
||||
|
||||
Are you getting stuck anywhere? Here are a few links to places to look:
|
||||
|
||||
* If you need help with developing your app, our [community Discord server][discord]
|
||||
is a great place to get advice from other Electron app developers.
|
||||
* If you suspect you're running into a bug with the `electron` package, please check
|
||||
the [GitHub issue tracker][issue-tracker] to see if any existing issues match your
|
||||
problem. If not, feel free to fill out our bug report template and submit a new issue.
|
||||
- If you need help with developing your app, our [community Discord server][discord]
|
||||
is a great place to get advice from other Electron app developers.
|
||||
- If you suspect you're running into a bug with the `electron` package, please check
|
||||
the [GitHub issue tracker][issue-tracker] to see if any existing issues match your
|
||||
problem. If not, feel free to fill out our bug report template and submit a new issue.
|
||||
|
||||
<!-- Links -->
|
||||
|
||||
[api documentation]: ../api/app.md
|
||||
[chromium]: https://www.chromium.org/
|
||||
[node]: https://nodejs.org/
|
||||
[mdn-guide]: https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web
|
||||
[node-guide]: https://nodejs.dev/learn
|
||||
[comic]: https://www.google.com/googlebooks/chrome/
|
||||
[discord]: https://discord.com/invite/APGC3k5yaH
|
||||
[examples]: examples.md
|
||||
[fiddle]: https://electronjs.org/fiddle
|
||||
[issue-tracker]: https://github.com/electron/electron/issues
|
||||
[discord]: https://discord.gg/electronjs
|
||||
[node]: https://nodejs.org/
|
||||
|
||||
@@ -379,7 +379,7 @@ module that uses the `webContents.send` API to send an IPC message from the main
|
||||
target renderer.
|
||||
|
||||
```javascript {11-26} title='main.js (Main Process)'
|
||||
const {app, BrowserWindow, Menu} = require('electron')
|
||||
const {app, BrowserWindow, Menu, ipcMain} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
@@ -413,7 +413,7 @@ function createWindow () {
|
||||
```
|
||||
|
||||
For the purposes of the tutorial, it's important to note that the `click` handler
|
||||
sends a message (either `1` or `-1`) to the renderer process through the `counter` channel.
|
||||
sends a message (either `1` or `-1`) to the renderer process through the `update-counter` channel.
|
||||
|
||||
```javascript
|
||||
click: () => mainWindow.webContents.send('update-counter', -1)
|
||||
@@ -519,7 +519,7 @@ window.electronAPI.onUpdateCounter((event, value) => {
|
||||
const oldValue = Number(counter.innerText)
|
||||
const newValue = oldValue + value
|
||||
counter.innerText = newValue
|
||||
event.reply('counter-value', newValue)
|
||||
event.sender.send('counter-value', newValue)
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@ your app.
|
||||
|
||||
Here is a very brief example of what a MessagePort is and how it works:
|
||||
|
||||
```js
|
||||
// renderer.js ///////////////////////////////////////////////////////////////
|
||||
```js title='renderer.js (Renderer Process)'
|
||||
// MessagePorts are created in pairs. A connected pair of message ports is
|
||||
// called a channel.
|
||||
const channel = new MessageChannel()
|
||||
@@ -28,8 +27,7 @@ port2.postMessage({ answer: 42 })
|
||||
ipcRenderer.postMessage('port', null, [port1])
|
||||
```
|
||||
|
||||
```js
|
||||
// main.js ///////////////////////////////////////////////////////////////////
|
||||
```js title='main.js (Main Process)'
|
||||
// In the main process, we receive the port.
|
||||
ipcMain.on('port', (event) => {
|
||||
// When we receive a MessagePort in the main process, it becomes a
|
||||
@@ -84,14 +82,84 @@ process, you can listen for the `close` event by calling `port.on('close',
|
||||
|
||||
## Example use cases
|
||||
|
||||
### Setting up a MessageChannel between two renderers
|
||||
|
||||
In this example, the main process sets up a MessageChannel, then sends each port
|
||||
to a different renderer. This allows renderers to send messages to each other
|
||||
without needing to use the main process as an in-between.
|
||||
|
||||
```js title='main.js (Main Process)'
|
||||
const { BrowserWindow, app, MessageChannelMain } = require('electron')
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
// create the windows.
|
||||
const mainWindow = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
contextIsolation: false,
|
||||
preload: 'preloadMain.js'
|
||||
}
|
||||
})
|
||||
|
||||
const secondaryWindow = BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
contextIsolation: false,
|
||||
preload: 'preloadSecondary.js'
|
||||
}
|
||||
})
|
||||
|
||||
// set up the channel.
|
||||
const { port1, port2 } = new MessageChannelMain()
|
||||
|
||||
// once the webContents are ready, send a port to each webContents with postMessage.
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
mainWindow.webContents.postMessage('port', null, [port1])
|
||||
})
|
||||
|
||||
secondaryWindow.once('ready-to-show', () => {
|
||||
secondaryWindow.webContents.postMessage('port', null, [port2])
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
Then, in your preload scripts you receive the port through IPC and set up the
|
||||
listeners.
|
||||
|
||||
```js title='preloadMain.js and preloadSecondary.js (Preload scripts)'
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
ipcRenderer.on('port', e => {
|
||||
// port received, make it globally available.
|
||||
window.electronMessagePort = e.ports[0]
|
||||
|
||||
window.electronMessagePort.onmessage = messageEvent => {
|
||||
// handle message
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
In this example messagePort is bound to the `window` object directly. It is better
|
||||
to use `contextIsolation` and set up specific contextBridge calls for each of your
|
||||
expected messages, but for the simplicity of this example we don't. You can find an
|
||||
example of context isolation further down this page at [Communicating directly between the main process and the main world of a context-isolated page](#communicating-directly-between-the-main-process-and-the-main-world-of-a-context-isolated-page)
|
||||
|
||||
That means window.messagePort is globally available and you can call
|
||||
`postMessage` on it from anywhere in your app to send a message to the other
|
||||
renderer.
|
||||
|
||||
```js title='renderer.js (Renderer Process)'
|
||||
// elsewhere in your code to send a message to the other renderers message handler
|
||||
window.electronMessagePort.postmessage('ping')
|
||||
```
|
||||
|
||||
### Worker process
|
||||
|
||||
In this example, your app has a worker process implemented as a hidden window.
|
||||
You want the app page to be able to communicate directly with the worker
|
||||
process, without the performance overhead of relaying via the main process.
|
||||
|
||||
```js
|
||||
// main.js ///////////////////////////////////////////////////////////////////
|
||||
```js title='main.js (Main Process)'
|
||||
const { BrowserWindow, app, ipcMain, MessageChannelMain } = require('electron')
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
@@ -129,8 +197,7 @@ app.whenReady().then(async () => {
|
||||
})
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- worker.html ------------------------------------------------------------>
|
||||
```html title='worker.html'
|
||||
<script>
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
@@ -153,8 +220,7 @@ ipcRenderer.on('new-client', (event) => {
|
||||
</script>
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- app.html --------------------------------------------------------------->
|
||||
```html title='app.html'
|
||||
<script>
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
@@ -182,9 +248,7 @@ Electron's built-in IPC methods only support two modes: fire-and-forget
|
||||
can implement a "response stream", where a single request responds with a
|
||||
stream of data.
|
||||
|
||||
```js
|
||||
// renderer.js ///////////////////////////////////////////////////////////////
|
||||
|
||||
```js title='renderer.js (Renderer Process)'
|
||||
const makeStreamingRequest = (element, callback) => {
|
||||
// MessageChannels are lightweight--it's cheap to create a new one for each
|
||||
// request.
|
||||
@@ -213,9 +277,7 @@ makeStreamingRequest(42, (data) => {
|
||||
// We will see "got response data: 42" 10 times.
|
||||
```
|
||||
|
||||
```js
|
||||
// main.js ///////////////////////////////////////////////////////////////////
|
||||
|
||||
```js title='main.js (Main Process)'
|
||||
ipcMain.on('give-me-a-stream', (event, msg) => {
|
||||
// The renderer has sent us a MessagePort that it wants us to send our
|
||||
// response over.
|
||||
@@ -242,8 +304,7 @@ the renderer are delivered to the isolated world, rather than to the main
|
||||
world. Sometimes you want to deliver messages to the main world directly,
|
||||
without having to step through the isolated world.
|
||||
|
||||
```js
|
||||
// main.js ///////////////////////////////////////////////////////////////////
|
||||
```js title='main.js (Main Process)'
|
||||
const { BrowserWindow, app, MessageChannelMain } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
@@ -278,8 +339,7 @@ app.whenReady().then(async () => {
|
||||
})
|
||||
```
|
||||
|
||||
```js
|
||||
// preload.js ////////////////////////////////////////////////////////////////
|
||||
```js title='preload.js (Preload Script)'
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
// We need to wait until the main world is ready to receive the message before
|
||||
@@ -297,8 +357,7 @@ ipcRenderer.on('main-world-port', async (event) => {
|
||||
})
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- index.html ------------------------------------------------------------->
|
||||
```html title='index.html'
|
||||
<script>
|
||||
window.onmessage = (event) => {
|
||||
// event.source === window means the message is coming from the preload
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
---
|
||||
title: 'Process Model'
|
||||
description: 'Electron inherits its multi-process architecture from Chromium, which makes the framework architecturally very similar to a modern web browser. This guide will expand on the concepts applied in the tutorial.'
|
||||
slug: process-model
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
# Process Model
|
||||
|
||||
Electron inherits its multi-process architecture from Chromium, which makes the framework
|
||||
architecturally very similar to a modern web browser. In this guide, we'll expound on
|
||||
the conceptual knowledge of Electron that we applied in the minimal [quick start app][].
|
||||
architecturally very similar to a modern web browser. This guide will expand on the
|
||||
concepts applied in the [Tutorial][tutorial].
|
||||
|
||||
[quick start app]: ./quick-start.md
|
||||
[tutorial]: ./tutorial-1-prerequisites.md
|
||||
|
||||
## Why not a single process?
|
||||
|
||||
@@ -27,10 +34,10 @@ visualizes this model:
|
||||

|
||||
|
||||
Electron applications are structured very similarly. As an app developer, you control
|
||||
two types of processes: main and renderer. These are analogous to Chrome's own browser
|
||||
and renderer processes outlined above.
|
||||
two types of processes: [main](#the-main-process) and [renderer](#the-renderer-process).
|
||||
These are analogous to Chrome's own browser and renderer processes outlined above.
|
||||
|
||||
[Chrome Comic]: https://www.google.com/googlebooks/chrome/
|
||||
[chrome comic]: https://www.google.com/googlebooks/chrome/
|
||||
|
||||
## The main process
|
||||
|
||||
@@ -68,7 +75,7 @@ When a `BrowserWindow` instance is destroyed, its corresponding renderer process
|
||||
terminated as well.
|
||||
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[web-embed]: ./web-embeds.md
|
||||
[web-embed]: ../tutorial/web-embeds.md
|
||||
[web-contents]: ../api/web-contents.md
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
|
||||
@@ -90,7 +97,7 @@ app.on('window-all-closed', () => {
|
||||
```
|
||||
|
||||
[app]: ../api/app.md
|
||||
[quick-start-lifecycle]: ./quick-start.md#manage-your-windows-lifecycle
|
||||
[quick-start-lifecycle]: ../tutorial/quick-start.md#manage-your-windows-lifecycle
|
||||
|
||||
### Native APIs
|
||||
|
||||
@@ -105,7 +112,7 @@ For a full list of Electron's main process modules, check out our API documentat
|
||||
|
||||
Each Electron app spawns a separate renderer process for each open `BrowserWindow`
|
||||
(and each web embed). As its name implies, a renderer is responsible for
|
||||
*rendering* web content. For all intents and purposes, code ran in renderer processes
|
||||
_rendering_ web content. For all intents and purposes, code ran in renderer processes
|
||||
should behave according to web standards (insofar as Chromium does, at least).
|
||||
|
||||
Therefore, all user interfaces and app functionality within a single browser
|
||||
@@ -115,18 +122,22 @@ web.
|
||||
Although explaining every web spec is out of scope for this guide, the bare minimum
|
||||
to understand is:
|
||||
|
||||
* An HTML file is your entry point for the renderer process.
|
||||
* UI styling is added through Cascading Style Sheets (CSS).
|
||||
* Executable JavaScript code can be added through `<script>` elements.
|
||||
- An HTML file is your entry point for the renderer process.
|
||||
- UI styling is added through Cascading Style Sheets (CSS).
|
||||
- Executable JavaScript code can be added through `<script>` elements.
|
||||
|
||||
Moreover, this also means that the renderer has no direct access to `require`
|
||||
or other Node.js APIs. In order to directly include NPM modules in the renderer,
|
||||
you must use the same bundler toolchains (for example, `webpack` or `parcel`) that you
|
||||
use on the web.
|
||||
|
||||
> Note: Renderer processes can be spawned with a full Node.js environment for ease of
|
||||
> development. Historically, this used to be the default, but this feature was disabled
|
||||
> for security reasons.
|
||||
:::warning
|
||||
|
||||
Renderer processes can be spawned with a full Node.js environment for ease of
|
||||
development. Historically, this used to be the default, but this feature was disabled
|
||||
for security reasons.
|
||||
|
||||
:::
|
||||
|
||||
At this point, you might be wondering how your renderer process user interfaces
|
||||
can interact with Node.js and Electron's native desktop functionality if these
|
||||
@@ -135,8 +146,9 @@ way to import Electron's content scripts.
|
||||
|
||||
## Preload scripts
|
||||
|
||||
<!-- Note: This guide doesn't take sandboxing into account, which might fundamentally
|
||||
<!-- Note: This guide doesn't take sandboxing into account, which might fundamentally
|
||||
change the statements here. -->
|
||||
|
||||
Preload scripts contain code that executes in a renderer process before its web content
|
||||
begins loading. These scripts run within the renderer context, but are granted more
|
||||
privileges by having access to Node.js APIs.
|
||||
@@ -149,8 +161,8 @@ const { BrowserWindow } = require('electron')
|
||||
//...
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: 'path/to/preload.js'
|
||||
}
|
||||
preload: 'path/to/preload.js',
|
||||
},
|
||||
})
|
||||
//...
|
||||
```
|
||||
@@ -165,7 +177,7 @@ the [`contextIsolation`][context-isolation] default.
|
||||
|
||||
```js title='preload.js'
|
||||
window.myAPI = {
|
||||
desktop: true
|
||||
desktop: true,
|
||||
}
|
||||
```
|
||||
|
||||
@@ -184,7 +196,7 @@ securely:
|
||||
const { contextBridge } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('myAPI', {
|
||||
desktop: true
|
||||
desktop: true,
|
||||
})
|
||||
```
|
||||
|
||||
@@ -195,14 +207,15 @@ console.log(window.myAPI)
|
||||
|
||||
This feature is incredibly useful for two main purposes:
|
||||
|
||||
* By exposing [`ipcRenderer`][ipcRenderer] helpers to the renderer, you can use
|
||||
- By exposing [`ipcRenderer`][ipcrenderer] helpers to the renderer, you can use
|
||||
inter-process communication (IPC) to trigger main process tasks from the
|
||||
renderer (and vice-versa).
|
||||
* If you're developing an Electron wrapper for an existing web app hosted on a remote
|
||||
- If you're developing an Electron wrapper for an existing web app hosted on a remote
|
||||
URL, you can add custom properties onto the renderer's `window` global that can
|
||||
be used for desktop-only logic on the web client's side.
|
||||
|
||||
[window-mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Window
|
||||
[context-isolation]: ./context-isolation.md
|
||||
[context-bridge]: ../api/context-bridge.md
|
||||
[ipcRenderer]: ../api/ipc-renderer.md
|
||||
[ipcrenderer]: ../api/ipc-renderer.md
|
||||
[tutorial]: ./tutorial-1-prerequisites.md
|
||||
|
||||
@@ -131,7 +131,6 @@ folder of your project:
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
<body>
|
||||
@@ -427,7 +426,6 @@ window.addEventListener('DOMContentLoaded', () => {
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -10,7 +10,7 @@ for answers to questions,
|
||||
or to join in discussion with other developers who use Electron,
|
||||
you can interact with the community in these locations:
|
||||
|
||||
* [`Electron's Discord`](https://discord.com/invite/electron) has channels for:
|
||||
* [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
|
||||
@@ -70,10 +70,10 @@ until the maintainers feel the maintenance burden is too high to continue doing
|
||||
|
||||
### Currently supported versions
|
||||
|
||||
* 18.x.y
|
||||
* 17.x.y
|
||||
* 16.x.y
|
||||
* 15.x.y
|
||||
* 14.x.y
|
||||
|
||||
### End-of-life
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
143
docs/tutorial/tutorial-1-prerequisites.md
Normal file
143
docs/tutorial/tutorial-1-prerequisites.md
Normal file
@@ -0,0 +1,143 @@
|
||||
---
|
||||
title: 'Prerequisites'
|
||||
description: 'This guide will step you through the process of creating a barebones Hello World app in Electron, similar to electron/electron-quick-start.'
|
||||
slug: tutorial-prerequisites
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
:::info Follow along the tutorial
|
||||
|
||||
This is **part 1** of the Electron tutorial.
|
||||
|
||||
1. **[Prerequisites][prerequisites]**
|
||||
1. [Building your First App][building your first app]
|
||||
1. [Using Preload Scripts][preload]
|
||||
1. [Adding Features][features]
|
||||
1. [Packaging Your Application][packaging]
|
||||
1. [Publishing and Updating][updates]
|
||||
|
||||
:::
|
||||
|
||||
Electron is a framework for building desktop applications using JavaScript,
|
||||
HTML, and CSS. By embedding [Chromium][chromium] and [Node.js][node] into a
|
||||
single binary file, Electron allows you to create cross-platform apps that
|
||||
work on Windows, macOS, and Linux with a single JavaScript codebase.
|
||||
|
||||
This tutorial will guide you through the process of developing a desktop
|
||||
application with Electron and distributing it to end users.
|
||||
|
||||
## Assumptions
|
||||
|
||||
Electron is a native wrapper layer for web apps and is run in a Node.js environment.
|
||||
Therefore, this tutorial assumes you are generally familiar with Node and
|
||||
front-end web development basics. If you need to do some background reading before
|
||||
continuing, we recommend the following resources:
|
||||
|
||||
- [Getting started with the Web (MDN Web Docs)][mdn-guide]
|
||||
- [Introduction to Node.js][node-guide]
|
||||
|
||||
## Required tools
|
||||
|
||||
### Code editor
|
||||
|
||||
You will need a text editor to write your code. We recommend using [Visual Studio Code],
|
||||
although you can choose whichever one you prefer.
|
||||
|
||||
### Command line
|
||||
|
||||
Throughout the tutorial, we will ask you to use various command-line interfaces (CLIs). You can
|
||||
type these commands into your system's default terminal:
|
||||
|
||||
- Windows: Command Prompt or PowerShell
|
||||
- macOS: Terminal
|
||||
- Linux: varies depending on distribution (e.g. GNOME Terminal, Konsole)
|
||||
|
||||
Most code editors also come with an integrated terminal, which you can also use.
|
||||
|
||||
### Git and GitHub
|
||||
|
||||
Git is a commonly-used version control system for source code, and GitHub is a collaborative
|
||||
development platform built on top of it. Although neither is strictly necessary to building
|
||||
an Electron application, we will use GitHub releases to set up automatic updates later
|
||||
on in the tutorial. Therefore, we'll require you to:
|
||||
|
||||
- [Create a GitHub account](https://github.com/join)
|
||||
- [Install Git](https://github.com/git-guides/install-git)
|
||||
|
||||
If you're unfamiliar with how Git works, we recommend reading GitHub's [Git guides]. You can also
|
||||
use the [GitHub Desktop] app if you prefer using a visual interface over the command line.
|
||||
|
||||
We recommend that you create a local Git repository and publish it to GitHub before starting
|
||||
the tutorial, and commit your code after every step.
|
||||
|
||||
:::info Installing Git via GitHub Desktop
|
||||
|
||||
GitHub Desktop will install the latest version of Git on your system if you don't already have
|
||||
it installed.
|
||||
|
||||
:::
|
||||
|
||||
### Node.js and npm
|
||||
|
||||
To begin developing an Electron app, you need to install the [Node.js][node-download]
|
||||
runtime and its bundled npm package manager onto your system. We recommend that you
|
||||
use the latest long-term support (LTS) version.
|
||||
|
||||
:::tip
|
||||
|
||||
Please install Node.js using pre-built installers for your platform.
|
||||
You may encounter incompatibility issues with different development tools otherwise.
|
||||
If you are using macOS, we recommend using a package manager like [Homebrew] or
|
||||
[nvm] to avoid any directory permission issues.
|
||||
|
||||
:::
|
||||
|
||||
To check that Node.js was installed correctly, you can use the `-v` flag when
|
||||
running the `node` and `npm` commands. These should print out the installed
|
||||
versions.
|
||||
|
||||
```sh
|
||||
$ node -v
|
||||
v16.14.2
|
||||
$ npm -v
|
||||
8.7.0
|
||||
```
|
||||
|
||||
:::caution
|
||||
|
||||
Although you need Node.js installed locally to scaffold an Electron project,
|
||||
Electron **does not use your system's Node.js installation to run its code**. Instead, it
|
||||
comes bundled with its own Node.js runtime. This means that your end users do not
|
||||
need to install Node.js themselves as a prerequisite to running your app.
|
||||
|
||||
To check which version of Node.js is running in your app, you can access the global
|
||||
[`process.versions`] variable in the main process or preload script. You can also reference
|
||||
the list of versions in the [electron/releases] repository.
|
||||
|
||||
:::
|
||||
|
||||
<!-- Links -->
|
||||
|
||||
[chromium]: https://www.chromium.org/
|
||||
[electron/releases]: https://github.com/electron/releases/blob/master/readme.md#releases
|
||||
[homebrew]: https://brew.sh/
|
||||
[mdn-guide]: https://developer.mozilla.org/en-US/docs/Learn/
|
||||
[node]: https://nodejs.org/
|
||||
[node-guide]: https://nodejs.dev/learn
|
||||
[node-download]: https://nodejs.org/en/download/
|
||||
[nvm]: https://github.com/nvm-sh/nvm
|
||||
[process-model]: ./process-model.md
|
||||
[`process.versions`]: https://nodejs.org/api/process.html#processversions
|
||||
[github]: https://github.com/
|
||||
[git guides]: https://github.com/git-guides/
|
||||
[github desktop]: https://desktop.github.com/
|
||||
[visual studio code]: https://code.visualstudio.com/
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
[prerequisites]: tutorial-1-prerequisites.md
|
||||
[building your first app]: tutorial-2-first-app.md
|
||||
[preload]: tutorial-3-preload.md
|
||||
[features]: tutorial-4-adding-features.md
|
||||
[packaging]: tutorial-5-packaging.md
|
||||
[updates]: tutorial-6-publishing-updating.md
|
||||
480
docs/tutorial/tutorial-2-first-app.md
Normal file
480
docs/tutorial/tutorial-2-first-app.md
Normal file
@@ -0,0 +1,480 @@
|
||||
---
|
||||
title: 'Building your First App'
|
||||
description: 'This guide will step you through the process of creating a barebones Hello World app in Electron, similar to electron/electron-quick-start.'
|
||||
slug: tutorial-first-app
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
:::info Follow along the tutorial
|
||||
|
||||
This is **part 2** of the Electron tutorial.
|
||||
|
||||
1. [Prerequisites][prerequisites]
|
||||
1. **[Building your First App][building your first app]**
|
||||
1. [Using Preload Scripts][preload]
|
||||
1. [Adding Features][features]
|
||||
1. [Packaging Your Application][packaging]
|
||||
1. [Publishing and Updating][updates]
|
||||
|
||||
:::
|
||||
|
||||
## Learning goals
|
||||
|
||||
In this part of the tutorial, you will learn how to set up your Electron project
|
||||
and write a minimal starter application. By the end of this section,
|
||||
you should be able to run a working Electron app in development mode from
|
||||
your terminal.
|
||||
|
||||
## Setting up your project
|
||||
|
||||
:::caution Avoid WSL
|
||||
|
||||
If you are on a Windows machine, please do not use [Windows Subsystem for Linux][wsl] (WSL)
|
||||
when following this tutorial as you will run into issues when trying to execute the
|
||||
application.
|
||||
|
||||
<!--https://www.electronforge.io/guides/developing-with-wsl-->
|
||||
|
||||
:::
|
||||
|
||||
### Initializing your npm project
|
||||
|
||||
Electron apps are scaffolded using npm, with the package.json file
|
||||
as an entry point. Start by creating a folder and initializing an npm package
|
||||
within it with `npm init`.
|
||||
|
||||
```sh npm2yarn
|
||||
mkdir my-electron-app && cd my-electron-app
|
||||
npm init
|
||||
```
|
||||
|
||||
This command will prompt you to configure some fields in your package.json.
|
||||
There are a few rules to follow for the purposes of this tutorial:
|
||||
|
||||
- _entry point_ should be `main.js` (you will be creating that file soon).
|
||||
- _author_, _license_, and _description_ can be any value, but will be necessary for
|
||||
[packaging][packaging] later on.
|
||||
|
||||
Then, install Electron into your app's **devDependencies**, which is the list of external
|
||||
development-only package dependencies not required in production.
|
||||
|
||||
:::info Why is Electron a devDependency?
|
||||
|
||||
This may seem counter-intuitive since your production code is running Electron APIs.
|
||||
However, packaged apps will come bundled with the Electron binary, eliminating the need to specify
|
||||
it as a production dependency.
|
||||
|
||||
:::
|
||||
|
||||
```sh npm2yarn
|
||||
npm install electron --save-dev
|
||||
```
|
||||
|
||||
Your package.json file should look something like this after initializing your package
|
||||
and installing Electron. You should also now have a `node_modules` folder containing
|
||||
the Electron executable, as well as a `package-lock.json` lockfile that specifies
|
||||
the exact dependency versions to install.
|
||||
|
||||
```json title='package.json'
|
||||
{
|
||||
"name": "my-electron-app",
|
||||
"version": "1.0.0",
|
||||
"description": "Hello World!",
|
||||
"main": "main.js",
|
||||
"author": "Jane Doe",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"electron": "19.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::info Advanced Electron installation steps
|
||||
|
||||
If installing Electron directly fails, please refer to our [Advanced Installation][installation]
|
||||
documentation for instructions on download mirrors, proxies, and troubleshooting steps.
|
||||
|
||||
:::
|
||||
|
||||
### Adding a .gitignore
|
||||
|
||||
The [`.gitignore`][gitignore] file specifies which files and directories to avoid tracking
|
||||
with Git. You should place a copy of [GitHub's Node.js gitignore template][gitignore-template]
|
||||
into your project's root folder to avoid committing your project's `node_modules` folder.
|
||||
|
||||
## Running an Electron app
|
||||
|
||||
:::tip Further reading
|
||||
|
||||
Read [Electron's process model][process-model] documentation to better
|
||||
understand how Electron's multiple processes work together.
|
||||
|
||||
:::
|
||||
|
||||
The [`main`][package-json-main] script you defined in package.json is the entry point of any
|
||||
Electron application. This script controls the **main process**, which runs in a Node.js
|
||||
environment and is responsible for controlling your app's lifecycle, displaying native
|
||||
interfaces, performing privileged operations, and managing renderer processes
|
||||
(more on that later).
|
||||
|
||||
Before creating your first Electron app, you will first use a trivial script to ensure your
|
||||
main process entry point is configured correctly. Create a `main.js` file in the root folder
|
||||
of your project with a single line of code:
|
||||
|
||||
```js title='main.js'
|
||||
console.log(`Hello from Electron 👋`)
|
||||
```
|
||||
|
||||
Because Electron's main process is a Node.js runtime, you can execute arbitrary Node.js code
|
||||
with the `electron` command (you can even use it as a [REPL]). To execute this script,
|
||||
add `electron .` to the `start` command in the [`scripts`][package-scripts]
|
||||
field of your package.json. This command will tell the Electron executable to look for the main
|
||||
script in the current directory and run it in dev mode.
|
||||
|
||||
```json {8-10} title='package.json'
|
||||
{
|
||||
"name": "my-electron-app",
|
||||
"version": "1.0.0",
|
||||
"description": "Hello World!",
|
||||
"main": "main.js",
|
||||
"author": "Jane Doe",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"start": "electron ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^19.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```sh npm2yarn
|
||||
npm run start
|
||||
```
|
||||
|
||||
Your terminal should print out `Hello from Electron 👋`. Congratulations,
|
||||
you have executed your first line of code in Electron! Next, you will learn
|
||||
how to create user interfaces with HTML and load that into a native window.
|
||||
|
||||
## Loading a web page into a BrowserWindow
|
||||
|
||||
In Electron, each window displays a web page that can be loaded either from a local HTML
|
||||
file or a remote web address. For this example, you will be loading in a local file. Start
|
||||
by creating a barebones web page in an `index.html` file in the root folder of your project:
|
||||
|
||||
```html 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'"
|
||||
/>
|
||||
<meta
|
||||
http-equiv="X-Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<title>Hello from Electron renderer!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello from Electron renderer!</h1>
|
||||
<p>👋</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Now that you have a web page, you can load it into an Electron [BrowserWindow][browser-window].
|
||||
Replace the contents your `main.js` file with the following code. We will explain each
|
||||
highlighted block separately.
|
||||
|
||||
```js {1,3-10,12-14} title='main.js' showLineNumbers
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
```
|
||||
|
||||
### Importing modules
|
||||
|
||||
```js title='main.js (Line 1)'
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
```
|
||||
|
||||
In the first line, we are importing two Electron modules
|
||||
with CommonJS module syntax:
|
||||
|
||||
- [app][app], which controls your application's event lifecycle.
|
||||
- [BrowserWindow][browser-window], which creates and manages app windows.
|
||||
|
||||
:::info Capitalization conventions
|
||||
|
||||
You might have noticed the capitalization difference between the **a**pp
|
||||
and **B**rowser**W**indow modules. Electron follows typical JavaScript conventions here,
|
||||
where PascalCase modules are instantiable class constructors (e.g. BrowserWindow, Tray,
|
||||
Notification) whereas camelCase modules are not instantiable (e.g. app, ipcRenderer, webContents).
|
||||
|
||||
:::
|
||||
|
||||
:::warning ES Modules in Electron
|
||||
|
||||
[ECMAScript modules](https://nodejs.org/api/esm.html) (i.e. using `import` to load a module)
|
||||
are currently not directly supported in Electron. You can find more information about the
|
||||
state of ESM in Electron in [electron/electron#21457](https://github.com/electron/electron/issues/21457).
|
||||
|
||||
:::
|
||||
|
||||
### Writing a reusable function to instantiate windows
|
||||
|
||||
The `createWindow()` function loads your web page into a new BrowserWindow instance:
|
||||
|
||||
```js title='main.js (Lines 3-10)'
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
```
|
||||
|
||||
### Calling your function when the app is ready
|
||||
|
||||
```js title='main.js (Lines 12-14)'
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
```
|
||||
|
||||
Many of Electron's core modules are Node.js [event emitters] that adhere to Node's asynchronous
|
||||
event-driven architecture. The app module is one of these emitters.
|
||||
|
||||
In Electron, BrowserWindows can only be created after the app module's [`ready`][app-ready] event
|
||||
is fired. You can wait for this event by using the [`app.whenReady()`][app-when-ready] API and
|
||||
calling `createWindow()` once its promise is fulfilled.
|
||||
|
||||
:::info
|
||||
|
||||
You typically listen to Node.js events by using an emitter's `.on` function.
|
||||
|
||||
```diff
|
||||
+ app.on('ready').then(() => {
|
||||
- app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
```
|
||||
|
||||
However, Electron exposes `app.whenReady()` as a helper specifically for the `ready` event to
|
||||
avoid subtle pitfalls with directly listening to that event in particular.
|
||||
See [electron/electron#21972](https://github.com/electron/electron/pull/21972) for details.
|
||||
|
||||
:::
|
||||
|
||||
At this point, running your Electron application's `start` command should successfully
|
||||
open a window that displays your web page!
|
||||
|
||||
Each web page your app displays in a window will run in a separate process called a
|
||||
**renderer** process (or simply _renderer_ for short). Renderer processes have access
|
||||
to the same JavaScript APIs and tooling you use for typical front-end web
|
||||
development, such as using [webpack] to bundle and minify your code or [React][react]
|
||||
to build your user interfaces.
|
||||
|
||||
## Managing your app's window lifecycle
|
||||
|
||||
Application windows behave differently on each operating system. Rather than
|
||||
enforce these conventions by default, Electron gives you the choice to implement
|
||||
them in your app code if you wish to follow them. You can implement basic window
|
||||
conventions by listening for events emitted by the app and BrowserWindow modules.
|
||||
|
||||
:::tip Process-specific control flow
|
||||
|
||||
Checking against Node's [`process.platform`][node-platform] variable can help you
|
||||
to run code conditionally on certain platforms. Note that there are only three
|
||||
possible platforms that Electron can run in: `win32` (Windows), `linux` (Linux),
|
||||
and `darwin` (macOS).
|
||||
|
||||
:::
|
||||
|
||||
### Quit the app when all windows are closed (Windows & Linux)
|
||||
|
||||
On Windows and Linux, closing all windows will generally quit an application entirely.
|
||||
To implement this pattern in your Electron app, listen for the app module's
|
||||
[`window-all-closed`][window-all-closed] event, and call [`app.quit()`][app-quit]
|
||||
to exit your app if the user is not on macOS.
|
||||
|
||||
```js
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
```
|
||||
|
||||
### Open a window if none are open (macOS)
|
||||
|
||||
In contrast, macOS apps generally continue running even without any windows open.
|
||||
Activating the app when no windows are available should open a new one.
|
||||
|
||||
To implement this feature, listen for the app module's [`activate`][activate]
|
||||
event, and call your existing `createWindow()` method if no BrowserWindows are open.
|
||||
|
||||
Because windows cannot be created before the `ready` event, you should only listen for
|
||||
`activate` events after your app is initialized. Do this by only listening for activate
|
||||
events inside your existing `whenReady()` callback.
|
||||
|
||||
```js
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Final starter code
|
||||
|
||||
```fiddle docs/fiddles/tutorial-first-app
|
||||
|
||||
```
|
||||
|
||||
## Optional: Debugging from VS Code
|
||||
|
||||
If you want to debug your application using VS Code, you have need attach VS Code to
|
||||
both the main and renderer processes. Here is a sample configuration for you to
|
||||
run. Create a launch.json configuration in a new `.vscode` folder in your project:
|
||||
|
||||
```json title='.vscode/launch.json'
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Main + renderer",
|
||||
"configurations": ["Main", "Renderer"],
|
||||
"stopAll": true
|
||||
}
|
||||
],
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Renderer",
|
||||
"port": 9222,
|
||||
"request": "attach",
|
||||
"type": "pwa-chrome",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"name": "Main",
|
||||
"type": "pwa-node",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
|
||||
"windows": {
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
|
||||
},
|
||||
"args": [".", "--remote-debugging-port=9222"],
|
||||
"outputCapture": "std",
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The "Main + renderer" option will appear when you select "Run and Debug"
|
||||
from the sidebar, allowing you to set breakpoints and inspect all the variables among
|
||||
other things in both the main and renderer processes.
|
||||
|
||||
What we have done in the `launch.json` file is to create 3 configurations:
|
||||
|
||||
- `Main` is used to start the main process and also expose port 9222 for remote debugging
|
||||
(`--remote-debugging-port=9222`). This is the port that we will use to attach the debugger
|
||||
for the `Renderer`. Because the main process is a Node.js process, the type is set to
|
||||
`pwa-node` (`pwa-` is the prefix that tells VS Code to use the latest JavaScript debugger).
|
||||
- `Renderer` is used to debug the renderer process. Because the main process is the one
|
||||
that creates the process, we have to "attach" to it (`"request": "attach"`) instead of
|
||||
creating a new one.
|
||||
The renderer process is a web one, so the debugger we have to use is `pwa-chrome`.
|
||||
- `Main + renderer` is a [compound task] that executes the previous ones simultaneously.
|
||||
|
||||
:::caution
|
||||
|
||||
Because we are attaching to a process in `Renderer`, it is possible that the first lines of
|
||||
your code will be skipped as the debugger will not have had enough time to connect before they are
|
||||
being executed.
|
||||
You can work around this by refreshing the page or setting a timeout before executing the code
|
||||
in development mode.
|
||||
|
||||
:::
|
||||
|
||||
:::info Further reading
|
||||
|
||||
If you want to dig deeper in the debugging area, the following guides provide more information:
|
||||
|
||||
- [Application Debugging]
|
||||
- [DevTools Extensions][devtools extension]
|
||||
|
||||
:::
|
||||
|
||||
## Summary
|
||||
|
||||
Electron applications are set up using npm packages. The Electron executable should be installed
|
||||
in your project's `devDependencies` and can be run in development mode using a script in your
|
||||
package.json file.
|
||||
|
||||
The executable runs the JavaScript entry point found in the `main` property of your package.json.
|
||||
This file controls Electron's **main process**, which runs an instance of Node.js and is
|
||||
responsible for your app's lifecycle, displaying native interfaces, performing privileged operations,
|
||||
and managing renderer processes.
|
||||
|
||||
**Renderer processes** (or renderers for short) are responsible for display graphical content. You can
|
||||
load a web page into a renderer by pointing it to either a web address or a local HTML file.
|
||||
Renderers behave very similarly to regular web pages and have access to the same web APIs.
|
||||
|
||||
In the next section of the tutorial, we will be learning how to augment the renderer process with
|
||||
privileged APIs and how to communicate between processes.
|
||||
|
||||
<!-- Links -->
|
||||
|
||||
[activate]: ../api/app.md#event-activate-macos
|
||||
[advanced-installation]: installation.md
|
||||
[app]: ../api/app.md
|
||||
[app-quit]: ../api/app.md#appquit
|
||||
[app-ready]: ../api/app.md#event-ready
|
||||
[app-when-ready]: ../api/app.md#appwhenready
|
||||
[application debugging]: ./application-debugging.md
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[commonjs]: https://nodejs.org/docs/../api/modules.html#modules_modules_commonjs_modules
|
||||
[compound task]: https://code.visualstudio.com/Docs/editor/tasks#_compound-tasks
|
||||
[devtools extension]: ./devtools-extension.md
|
||||
[event emitters]: https://nodejs.org/api/events.html#events
|
||||
[gitignore]: https://git-scm.com/docs/gitignore
|
||||
[gitignore-template]: https://github.com/github/gitignore/blob/main/Node.gitignore
|
||||
[installation]: ./installation.md
|
||||
[node-platform]: https://nodejs.org/api/process.html#process_process_platform
|
||||
[package-json-main]: https://docs.npmjs.com/cli/v7/configuring-npm/package-json#main
|
||||
[package-scripts]: https://docs.npmjs.com/cli/v7/using-npm/scripts
|
||||
[process-model]: process-model.md
|
||||
[react]: https://reactjs.org
|
||||
[repl]: ./repl.md
|
||||
[sandbox]: ./sandbox.md
|
||||
[webpack]: https://webpack.js.org
|
||||
[window-all-closed]: ../api/app.md#event-window-all-closed
|
||||
[wsl]: https://docs.microsoft.com/en-us/windows/wsl/about#what-is-wsl-2
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
[prerequisites]: tutorial-1-prerequisites.md
|
||||
[building your first app]: tutorial-2-first-app.md
|
||||
[preload]: tutorial-3-preload.md
|
||||
[features]: tutorial-4-adding-features.md
|
||||
[packaging]: tutorial-5-packaging.md
|
||||
[updates]: tutorial-6-publishing-updating.md
|
||||
271
docs/tutorial/tutorial-3-preload.md
Normal file
271
docs/tutorial/tutorial-3-preload.md
Normal file
@@ -0,0 +1,271 @@
|
||||
---
|
||||
title: 'Using Preload Scripts'
|
||||
description: 'This guide will step you through the process of creating a barebones Hello World app in Electron, similar to electron/electron-quick-start.'
|
||||
slug: tutorial-preload
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
:::info Follow along the tutorial
|
||||
|
||||
This is **part 3** of the Electron tutorial.
|
||||
|
||||
1. [Prerequisites][prerequisites]
|
||||
1. [Building your First App][building your first app]
|
||||
1. **[Using Preload Scripts][preload]**
|
||||
1. [Adding Features][features]
|
||||
1. [Packaging Your Application][packaging]
|
||||
1. [Publishing and Updating][updates]
|
||||
|
||||
:::
|
||||
|
||||
## Learning goals
|
||||
|
||||
In this part of the tutorial, you will learn what a preload script is and how to use one
|
||||
to securely expose privileged APIs into the renderer process. You will also learn how to
|
||||
communicate between main and renderer processes with Electron's inter-process
|
||||
communication (IPC) modules.
|
||||
|
||||
## What is a preload script?
|
||||
|
||||
Electron's main process is a Node.js environment that has full operating system access.
|
||||
On top of [Electron modules][modules], you can also access [Node.js built-ins][node-api],
|
||||
as well as any packages installed via npm. On the other hand, renderer processes run web
|
||||
pages and do not run Node.js by default for security reasons.
|
||||
|
||||
To bridge Electron's different process types together, we will need to use a special script
|
||||
called a **preload**.
|
||||
|
||||
## Augmenting the renderer with a preload script
|
||||
|
||||
A BrowserWindow's preload script runs in a context that has access to both the HTML DOM
|
||||
and a Node.js environment. Preload scripts are injected before a web page loads in the renderer,
|
||||
similar to a Chrome extension's [content scripts][content-script]. To add features to your renderer
|
||||
that require privileged access, you can define [global] objects through the
|
||||
[contextBridge][contextbridge] API.
|
||||
|
||||
To demonstrate this concept, you will create a preload script that exposes your app's
|
||||
versions of Chrome, Node, and Electron into the renderer.
|
||||
|
||||
Add a new `preload.js` script that exposes selected properties of Electron's `process.versions`
|
||||
object to the renderer process in a `versions` global variable.
|
||||
|
||||
```js title="preload.js"
|
||||
const { contextBridge } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('versions', {
|
||||
node: () => process.versions.node,
|
||||
chrome: () => process.versions.chrome,
|
||||
electron: () => process.versions.electron,
|
||||
// we can also expose variables, not just functions
|
||||
})
|
||||
```
|
||||
|
||||
To attach this script to your renderer process, pass its path to the
|
||||
`webPreferences.preload` option in the BrowserWindow constructor:
|
||||
|
||||
```js {8-10} title="main.js"
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
},
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
```
|
||||
|
||||
:::info
|
||||
|
||||
There are two Node.js concepts that are used here:
|
||||
|
||||
- The [`__dirname`][dirname] string points to the path of the currently executing script
|
||||
(in this case, your project's root folder).
|
||||
- The [`path.join`][path-join] API joins multiple path segments together, creating a
|
||||
combined path string that works across all platforms.
|
||||
|
||||
:::
|
||||
|
||||
At this point, the renderer has access to the `versions` global, so let's display that
|
||||
information in the window. This variable can be accessed via `window.versions` or simply
|
||||
`versions`. Create a `renderer.js` script that uses the [`document.getElementById`]
|
||||
DOM API to replace the displayed text for the HTML element with `info` as its `id` property.
|
||||
|
||||
```js title="renderer.js"
|
||||
const information = document.getElementById('info')
|
||||
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`
|
||||
```
|
||||
|
||||
Then, modify your `index.html` by adding a new element with `info` as its `id` property,
|
||||
and attach your `renderer.js` script:
|
||||
|
||||
```html {18,20} title="index.html"
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<meta
|
||||
http-equiv="X-Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<title>Hello from Electron renderer!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello from Electron renderer!</h1>
|
||||
<p>👋</p>
|
||||
<p id="info"></p>
|
||||
</body>
|
||||
<script src="./renderer.js"></script>
|
||||
</html>
|
||||
```
|
||||
|
||||
After following the above steps, your app should look something like this:
|
||||
|
||||

|
||||
|
||||
And the code should look like this:
|
||||
|
||||
```fiddle docs/fiddles/tutorial-preload
|
||||
|
||||
```
|
||||
|
||||
## Communicating between processes
|
||||
|
||||
As we have mentioned above, Electron's main and renderer process have distinct responsibilities
|
||||
and are not interchangeable. This means it is not possible to access the Node.js APIs directly
|
||||
from the renderer process, nor the HTML Document Object Model (DOM) from the main process.
|
||||
|
||||
The solution for this problem is to use Electron's `ipcMain` and `ipcRenderer` modules for
|
||||
inter-process communication (IPC). To send a message from your web page to the main process,
|
||||
you can set up a main process handler with `ipcMain.handle` and
|
||||
then expose a function that calls `ipcRenderer.invoke` to trigger the handler in your preload script.
|
||||
|
||||
To illustrate, we will add a global function to the renderer called `ping()`
|
||||
that will return a string from the main process.
|
||||
|
||||
First, set up the `invoke` call in your preload script:
|
||||
|
||||
```js {1,7} title="preload.js"
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('versions', {
|
||||
node: () => process.versions.node,
|
||||
chrome: () => process.versions.chrome,
|
||||
electron: () => process.versions.electron,
|
||||
ping: () => ipcRenderer.invoke('ping'),
|
||||
// we can also expose variables, not just functions
|
||||
})
|
||||
```
|
||||
|
||||
:::caution IPC security
|
||||
|
||||
Notice how we wrap the `ipcRenderer.invoke('ping')` call in a helper function rather
|
||||
than expose the `ipcRenderer` module directly via context bridge. You **never** want to
|
||||
directly expose the entire `ipcRenderer` module via preload. This would give your renderer
|
||||
the ability to send arbitrary IPC messages to the main process, which becomes a powerful
|
||||
attack vector for malicious code.
|
||||
|
||||
:::
|
||||
|
||||
Then, set up your `handle` listener in the main process. We do this _before_
|
||||
loading the HTML file so that the handler is guaranteed to be ready before
|
||||
you send out the `invoke` call from the renderer.
|
||||
|
||||
```js {1,11} title="main.js"
|
||||
const { ipcMain } = require('electron')
|
||||
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
},
|
||||
})
|
||||
ipcMain.handle('ping', () => 'pong')
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
```
|
||||
|
||||
Once you have the sender and receiver set up, you can now send messages from the renderer
|
||||
to the main process through the `'ping'` channel you just defined.
|
||||
|
||||
```js title='renderer.js'
|
||||
const func = async () => {
|
||||
const response = await window.versions.ping()
|
||||
console.log(response) // prints out 'pong'
|
||||
}
|
||||
|
||||
func()
|
||||
```
|
||||
|
||||
:::info
|
||||
|
||||
For more in-depth explanations on using the `ipcRenderer` and `ipcMain` modules,
|
||||
check out the full [Inter-Process Communication][ipc] guide.
|
||||
|
||||
:::
|
||||
|
||||
## Summary
|
||||
|
||||
A preload script contains code that runs before your web page is loaded into the browser
|
||||
window. It has access to both DOM APIs and Node.js environment, and is often used to
|
||||
expose privileged APIs to the renderer via the `contextBridge` API.
|
||||
|
||||
Because the main and renderer processes have very different responsibilities, Electron
|
||||
apps often use the preload script to set up inter-process communication (IPC) interfaces
|
||||
to pass arbitrary messages between the two kinds of processes.
|
||||
|
||||
In the next part of the tutorial, we will be showing you resources on adding more
|
||||
functionality to your app, then teaching you distributing your app to users.
|
||||
|
||||
<!-- Links -->
|
||||
|
||||
[advanced-installation]: ./installation.md
|
||||
[application debugging]: ./application-debugging.md
|
||||
[app]: ../api/app.md
|
||||
[app-ready]: ../api/app.md#event-ready
|
||||
[app-when-ready]: ../api/app.md#appwhenready
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[commonjs]: https://nodejs.org/docs/latest/api/modules.html#modules_modules_commonjs_modules
|
||||
[compound task]: https://code.visualstudio.com/Docs/editor/tasks#_compound-tasks
|
||||
[content-script]: https://developer.chrome.com/docs/extensions/mv3/content_scripts/
|
||||
[contextbridge]: ../api/context-bridge.md
|
||||
[context-isolation]: ./context-isolation.md
|
||||
[`document.getelementbyid`]: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById
|
||||
[devtools-extension]: ./devtools-extension.md
|
||||
[dirname]: https://nodejs.org/api/modules.html#modules_dirname
|
||||
[global]: https://developer.mozilla.org/en-US/docs/Glossary/Global_object
|
||||
[ipc]: ./ipc.md
|
||||
[mdn-csp]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
|
||||
[modules]: ../api/app.md
|
||||
[node-api]: https://nodejs.org/dist/latest/docs/api/
|
||||
[package-json-main]: https://docs.npmjs.com/cli/v7/configuring-npm/package-json#main
|
||||
[package-scripts]: https://docs.npmjs.com/cli/v7/using-npm/scripts
|
||||
[path-join]: https://nodejs.org/api/path.html#path_path_join_paths
|
||||
[process-model]: ./process-model.md
|
||||
[react]: https://reactjs.org
|
||||
[sandbox]: ./sandbox.md
|
||||
[webpack]: https://webpack.js.org
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
[prerequisites]: tutorial-1-prerequisites.md
|
||||
[building your first app]: tutorial-2-first-app.md
|
||||
[preload]: tutorial-3-preload.md
|
||||
[features]: tutorial-4-adding-features.md
|
||||
[packaging]: tutorial-5-packaging.md
|
||||
[updates]: tutorial-6-publishing-updating.md
|
||||
77
docs/tutorial/tutorial-4-adding-features.md
Normal file
77
docs/tutorial/tutorial-4-adding-features.md
Normal file
@@ -0,0 +1,77 @@
|
||||
---
|
||||
title: 'Adding Features'
|
||||
description: 'In this step of the tutorial, we will share some resources you should read to add features to your application'
|
||||
slug: tutorial-adding-features
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
:::info Follow along the tutorial
|
||||
|
||||
This is **part 4** of the Electron tutorial.
|
||||
|
||||
1. [Prerequisites][prerequisites]
|
||||
1. [Building your First App][building your first app]
|
||||
1. [Using Preload Scripts][preload]
|
||||
1. **[Adding Features][features]**
|
||||
1. [Packaging Your Application][packaging]
|
||||
1. [Publishing and Updating][updates]
|
||||
|
||||
:::
|
||||
|
||||
## Adding application complexity
|
||||
|
||||
If you have been following along, you should have a functional Electron application
|
||||
with a static user interface. From this starting point, you can generally progress
|
||||
in developing your app in two broad directions:
|
||||
|
||||
1. Adding complexity to your renderer process' web app code
|
||||
1. Deeper integrations with the operating system and Node.js
|
||||
|
||||
It is important to understand the distinction between these two broad concepts. For the
|
||||
first point, Electron-specific resources are not necessary. Building a pretty to-do
|
||||
list in Electron is just pointing your Electron BrowserWindow to a pretty
|
||||
to-do list web app. Ultimately, you are building your renderer's UI using the same tools
|
||||
(HTML, CSS, JavaScript) that you would on the web. Therefore, Electron's docs will
|
||||
not go in-depth on how to use standard web tools.
|
||||
|
||||
On the other hand, Electron also provides a rich set of tools that allow
|
||||
you to integrate with the desktop environment, from creating tray icons to adding
|
||||
global shortcuts to displaying native menus. It also gives you all the power of a
|
||||
Node.js environment in the main process. This set of capabilities separates
|
||||
Electron applications from running a website in a browser tab, and are the
|
||||
focus of Electron's documentation.
|
||||
|
||||
## How-to examples
|
||||
|
||||
Electron's documentation has many tutorials to help you with more advanced topics
|
||||
and deeper operating system integrations. To get started, check out the
|
||||
[How-To Examples][how-to] doc.
|
||||
|
||||
:::note Let us know if something is missing!
|
||||
|
||||
If you can't find what you are looking for, please let us know on [GitHub] or in
|
||||
our [Discord server][discord]!
|
||||
|
||||
:::
|
||||
|
||||
## What's next?
|
||||
|
||||
For the rest of the tutorial, we will be shifting away from application code
|
||||
and giving you a look at how you can get your app from your developer machine
|
||||
into end users' hands.
|
||||
|
||||
<!-- Link labels -->
|
||||
|
||||
[discord]: https://discord.com/invite/APGC3k5yaH
|
||||
[github]: https://github.com/electron/electronjs.org-new/issues/new
|
||||
[how to]: ./examples.md
|
||||
[node-platform]: https://nodejs.org/api/process.html#process_process_platform
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
[prerequisites]: tutorial-1-prerequisites.md
|
||||
[building your first app]: tutorial-2-first-app.md
|
||||
[preload]: tutorial-3-preload.md
|
||||
[features]: tutorial-4-adding-features.md
|
||||
[packaging]: tutorial-5-packaging.md
|
||||
[updates]: tutorial-6-publishing-updating.md
|
||||
225
docs/tutorial/tutorial-5-packaging.md
Normal file
225
docs/tutorial/tutorial-5-packaging.md
Normal file
@@ -0,0 +1,225 @@
|
||||
---
|
||||
title: 'Packaging Your Application'
|
||||
description: 'To distribute your app with Electron, you need to package it and create installers.'
|
||||
slug: tutorial-packaging
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
:::info Follow along the tutorial
|
||||
|
||||
This is **part 5** of the Electron tutorial.
|
||||
|
||||
1. [Prerequisites][prerequisites]
|
||||
1. [Building your First App][building your first app]
|
||||
1. [Using Preload Scripts][preload]
|
||||
1. [Adding Features][features]
|
||||
1. **[Packaging Your Application][packaging]**
|
||||
1. [Publishing and Updating][updates]
|
||||
|
||||
:::
|
||||
|
||||
## Learning goals
|
||||
|
||||
In this part of the tutorial, we'll be going over the basics of packaging and distributing
|
||||
your app with [Electron Forge].
|
||||
|
||||
## Using Electron Forge
|
||||
|
||||
Electron does not have any tooling for packaging and distribution bundled into its core
|
||||
modules. Once you have a working Electron app in dev mode, you need to use
|
||||
additional tooling to create a packaged app you can distribute to your users (also known
|
||||
as a **distributable**). Distributables can be either installers (e.g. MSI on Windows) or
|
||||
portable executable files (e.g. `.app` on macOS).
|
||||
|
||||
Electron Forge is an all-in-one tool that handles the packaging and distribution of Electron
|
||||
apps. Under the hood, it combines a lot of existing Electron tools (e.g. [`electron-packager`],
|
||||
[`@electron/osx-sign`], [`electron-winstaller`], etc.) into a single interface so you do not
|
||||
have to worry about wiring them all together.
|
||||
|
||||
### Importing your project into Forge
|
||||
|
||||
You can install Electron Forge's CLI in your project's `devDependencies` and import your
|
||||
existing project with a handy conversion script.
|
||||
|
||||
```sh npm2yarn
|
||||
npm install --save-dev @electron-forge/cli
|
||||
npx electron-forge import
|
||||
```
|
||||
|
||||
Once the conversion script is done, Forge should have added a few scripts
|
||||
to your `package.json` file.
|
||||
|
||||
```json title='package.json'
|
||||
//...
|
||||
"scripts": {
|
||||
"start": "electron-forge start",
|
||||
"package": "electron-forge package",
|
||||
"make": "electron-forge make"
|
||||
},
|
||||
//...
|
||||
```
|
||||
|
||||
:::info CLI documentation
|
||||
|
||||
For more information on `make` and other Forge APIs, check out
|
||||
the [Electron Forge CLI documentation].
|
||||
|
||||
:::
|
||||
|
||||
You should also notice that your package.json now has a few more packages installed
|
||||
under your `devDependencies`, and contains an added `config.forge` field with an array
|
||||
of makers configured. **Makers** are Forge plugins that create distributables from
|
||||
your source code. You should see multiple makers in the pre-populated configuration,
|
||||
one for each target platform.
|
||||
|
||||
### Creating a distributable
|
||||
|
||||
To create a distributable, use your project's new `make` script, which runs the
|
||||
`electron-forge make` command.
|
||||
|
||||
```sh npm2yarn
|
||||
npm run make
|
||||
```
|
||||
|
||||
This `make` command contains two steps:
|
||||
|
||||
1. It will first run `electron-forge package` under the hood, which bundles your app
|
||||
code together with the Electron binary. The packaged code is generated into a folder.
|
||||
1. It will then use this packaged app folder to create a separate distributable for each
|
||||
configured maker.
|
||||
|
||||
After the script runs, you should see an `out` folder containing both the distributable
|
||||
and a folder containing the packaged application code.
|
||||
|
||||
```plain title='macOS output example'
|
||||
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
|
||||
```
|
||||
|
||||
The distributable in the `out/make` folder should be ready to launch! You have now
|
||||
created your first bundled Electron application.
|
||||
|
||||
:::tip Distributable formats
|
||||
|
||||
Electron Forge can be configured to create distributables in different OS-specific formats
|
||||
(e.g. DMG, deb, MSI, etc.). See Forge's [Makers] documentation for all configuration options.
|
||||
|
||||
:::
|
||||
|
||||
:::note Packaging without Electron Forge
|
||||
|
||||
If you want to manually package your code, or if you're just interested understanding the
|
||||
mechanics behind packaging an Electron app, check out the full [Application Packaging]
|
||||
documentation.
|
||||
|
||||
:::
|
||||
|
||||
## Important: signing your code
|
||||
|
||||
In order to distribute desktop applications to end users, we _highly recommended_ for you
|
||||
to **code sign** your Electron app. Code signing is an important part of shipping
|
||||
desktop applications, and is mandatory for the auto-update step in the final part
|
||||
of the tutorial.
|
||||
|
||||
Code signing is a security technology that you use to certify that a desktop app was
|
||||
created by a known source. Windows and macOS have their own OS-specific code signing
|
||||
systems that will make it difficult for users to download or launch unsigned applications.
|
||||
|
||||
If you already have code signing certificates for Windows and macOS, you can set your
|
||||
credentials in your Forge configuration. Otherwise, please refer to the full
|
||||
[Code Signing] documentation to learn how to purchase a certificate and for more information
|
||||
on the desktop app code signing process.
|
||||
|
||||
On macOS, code signing is done at the app packaging level. On Windows, distributable installers
|
||||
are signed instead.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="macos" label="macOS" default>
|
||||
|
||||
```json title='package.json' {6-18}
|
||||
{
|
||||
//...
|
||||
"config": {
|
||||
"forge": {
|
||||
//...
|
||||
"packagerConfig": {
|
||||
"osxSign": {
|
||||
"identity": "Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)",
|
||||
"hardened-runtime": true,
|
||||
"entitlements": "entitlements.plist",
|
||||
"entitlements-inherit": "entitlements.plist",
|
||||
"signature-flags": "library"
|
||||
},
|
||||
"osxNotarize": {
|
||||
"appleId": "felix@felix.fun",
|
||||
"appleIdPassword": "this-is-a-secret"
|
||||
}
|
||||
}
|
||||
//...
|
||||
}
|
||||
}
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="windows" label="Windows">
|
||||
|
||||
```json title='package.json' {6-14}
|
||||
{
|
||||
//...
|
||||
"config": {
|
||||
"forge": {
|
||||
//...
|
||||
"makers": [
|
||||
{
|
||||
"name": "@electron-forge/maker-squirrel",
|
||||
"config": {
|
||||
"certificateFile": "./cert.pfx",
|
||||
"certificatePassword": "this-is-a-secret"
|
||||
}
|
||||
}
|
||||
]
|
||||
//...
|
||||
}
|
||||
}
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Summary
|
||||
|
||||
Electron applications need to be packaged to be distributed to users. In this tutorial,
|
||||
you imported your app into Electron Forge and configured it to package your app and
|
||||
generate installers.
|
||||
|
||||
In order for your application to be trusted by the user's system, you need to digitally
|
||||
certify that the distributable is authentic and untampered by code signing it. Your app
|
||||
can be signed through Forge once you configure it to use your code signing certificate
|
||||
information.
|
||||
|
||||
[`@electron/osx-sign`]: https://github.com/electron/osx-sign
|
||||
[application packaging]: ./application-distribution.md
|
||||
[code signing]: ./code-signing.md
|
||||
[`electron-packager`]: https://github.com/electron/electron-packager
|
||||
[`electron-winstaller`]: https://github.com/electron/windows-installer
|
||||
[electron forge]: https://www.electronforge.io
|
||||
[electron forge cli documentation]: https://www.electronforge.io/cli#commands
|
||||
[makers]: https://www.electronforge.io/config/makers
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
[prerequisites]: tutorial-1-prerequisites.md
|
||||
[building your first app]: tutorial-2-first-app.md
|
||||
[preload]: tutorial-3-preload.md
|
||||
[features]: tutorial-4-adding-features.md
|
||||
[packaging]: tutorial-5-packaging.md
|
||||
[updates]: tutorial-6-publishing-updating.md
|
||||
251
docs/tutorial/tutorial-6-publishing-updating.md
Normal file
251
docs/tutorial/tutorial-6-publishing-updating.md
Normal file
@@ -0,0 +1,251 @@
|
||||
---
|
||||
title: 'Publishing and Updating'
|
||||
description: "There are several ways to update an Electron application. The easiest and officially supported one is taking advantage of the built-in Squirrel framework and Electron's autoUpdater module."
|
||||
slug: tutorial-publishing-updating
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
:::info Follow along the tutorial
|
||||
|
||||
This is **part 6** of the Electron tutorial.
|
||||
|
||||
1. [Prerequisites][prerequisites]
|
||||
1. [Building your First App][building your first app]
|
||||
1. [Using Preload Scripts][preload]
|
||||
1. [Adding Features][features]
|
||||
1. [Packaging Your Application][packaging]
|
||||
1. **[Publishing and Updating][updates]**
|
||||
|
||||
:::
|
||||
|
||||
## Learning goals
|
||||
|
||||
If you've been following along, this is the last step of the tutorial! In this part,
|
||||
you will publish your app to GitHub releases and integrate automatic updates
|
||||
into your app code.
|
||||
|
||||
## Using update.electronjs.org
|
||||
|
||||
The Electron maintainers provide a free auto-updating service for open-source apps
|
||||
at https://update.electronjs.org. Its requirements are:
|
||||
|
||||
- Your app runs on macOS or Windows
|
||||
- Your app has a public GitHub repository
|
||||
- Builds are published to [GitHub releases]
|
||||
- Builds are [code signed][code-signed]
|
||||
|
||||
At this point, we'll assume that you have already pushed all your
|
||||
code to a public GitHub repository.
|
||||
|
||||
:::info Alternative update services
|
||||
|
||||
If you're using an alternate repository host (e.g. GitLab or Bitbucket) or if
|
||||
you need to keep your code repository private, please refer to our
|
||||
[step-by-step guide][update-server] on hosting your own Electron update server.
|
||||
|
||||
:::
|
||||
|
||||
## Publishing a GitHub release
|
||||
|
||||
Electron Forge has [Publisher] plugins that can automate the distribution
|
||||
of your packaged application to various sources. In this tutorial, we will
|
||||
be using the GitHub Publisher, which will allow us to publish
|
||||
our code to GitHub releases.
|
||||
|
||||
### Generating a personal access token
|
||||
|
||||
Forge cannot publish to any repository on GitHub without permission. You
|
||||
need to pass in an authenticated token that gives Forge access to
|
||||
your GitHub releases. The easiest way to do this is to
|
||||
[create a new personal access token (PAT)][new-pat]
|
||||
with the `public_repo` scope, which gives write access to your public repositories.
|
||||
**Make sure to keep this token a secret.**
|
||||
|
||||
### Setting up the GitHub Publisher
|
||||
|
||||
#### Installing the module
|
||||
|
||||
Forge's [GitHub Publisher] is a plugin that
|
||||
needs to be installed in your project's `devDependencies`:
|
||||
|
||||
```sh npm2yarn
|
||||
npm install --save-dev @electron-forge/publisher-github
|
||||
```
|
||||
|
||||
#### Configuring the publisher in Forge
|
||||
|
||||
Once you have it installed, you need to set it up in your Forge
|
||||
configuration. A full list of options is documented in the Forge's
|
||||
[`PublisherGitHubConfig`] API docs.
|
||||
|
||||
```json title='package.json' {6-16}
|
||||
{
|
||||
//...
|
||||
"config": {
|
||||
"forge": {
|
||||
"publishers": [
|
||||
{
|
||||
"name": "@electron-forge/publisher-github",
|
||||
"config": {
|
||||
"repository": {
|
||||
"owner": "github-user-name",
|
||||
"name": "github-repo-name"
|
||||
},
|
||||
"prerelease": false,
|
||||
"draft": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
:::tip Drafting releases before publishing
|
||||
|
||||
Notice that you have configured Forge to publish your release as a draft.
|
||||
This will allow you to see the release with its generated artifacts
|
||||
without actually publishing it to your end users. You can manually
|
||||
publish your releases via GitHub after writing release notes and
|
||||
double-checking that your distributables work.
|
||||
|
||||
:::
|
||||
|
||||
#### Setting up your authentication token
|
||||
|
||||
You also need to make the Publisher aware of your authentication token.
|
||||
By default, it will use the value stored in the `GITHUB_TOKEN` environment
|
||||
variable.
|
||||
|
||||
### Running the publish command
|
||||
|
||||
Add Forge's [publish command] to your npm scripts.
|
||||
|
||||
```json {6} title='package.json'
|
||||
//...
|
||||
"scripts": {
|
||||
"start": "electron-forge start",
|
||||
"package": "electron-forge package",
|
||||
"make": "electron-forge make",
|
||||
"publish": "electron-forge publish"
|
||||
},
|
||||
//...
|
||||
```
|
||||
|
||||
This command will run your configured makers and publish the output distributables to a new
|
||||
GitHub release.
|
||||
|
||||
```sh npm2yarn
|
||||
npm run publish
|
||||
```
|
||||
|
||||
By default, this will only publish a single distributable for your host operating system and
|
||||
architecture. You can publish for different architectures by passing in the `--arch` flag to your
|
||||
Forge commands.
|
||||
|
||||
The name of this release will correspond to the `version` field in your project's package.json file.
|
||||
|
||||
:::tip Tagging releases
|
||||
|
||||
Optionally, you can also [tag your releases in Git][git-tag] so that your
|
||||
release is associated with a labeled point in your code history. npm comes
|
||||
with a handy [`npm version`](https://docs.npmjs.com/cli/v8/commands/npm-version)
|
||||
command that can handle the version bumping and tagging for you.
|
||||
|
||||
:::
|
||||
|
||||
#### Bonus: Publishing in GitHub Actions
|
||||
|
||||
Publishing locally can be painful, especially because you can only create distributables
|
||||
for your host operating system (i.e. you can't publish a Window `.exe` file from macOS).
|
||||
|
||||
A solution for this would be to publish your app via automation workflows
|
||||
such as [GitHub Actions], which can run tasks in the
|
||||
cloud on Ubuntu, macOS, and Windows. This is the exact approach taken by [Electron Fiddle].
|
||||
You can refer to Fiddle's [Build and Release pipeline][fiddle-build]
|
||||
and [Forge configuration][fiddle-forge-config]
|
||||
for more details.
|
||||
|
||||
## Instrumenting your updater code
|
||||
|
||||
Now that we have a functional release system via GitHub releases, we now need to tell our
|
||||
Electron app to download an update whenever a new release is out. Electron apps do this
|
||||
via the [autoUpdater] module, which reads from an update server feed to check if a new version
|
||||
is available for download.
|
||||
|
||||
The update.electronjs.org service provides an updater-compatible feed. For example, Electron
|
||||
Fiddle v0.28.0 will check the endpoint at https://update.electronjs.org/electron/fiddle/darwin/v0.28.0
|
||||
to see if a newer GitHub release is available.
|
||||
|
||||
After your release is published to GitHub, the update.electronjs.org service should work
|
||||
for your application. The only step left is to configure the feed with the autoUpdater module.
|
||||
|
||||
To make this process easier, the Electron team maintains the [`update-electron-app`] module,
|
||||
which sets up the autoUpdater boilerplate for update.electronjs.org in one function
|
||||
call — no configuration required. This module will search for the update.electronjs.org
|
||||
feed that matches your project's package.json `"repository"` field.
|
||||
|
||||
First, install the module as a runtime dependency.
|
||||
|
||||
```sh npm2yarn
|
||||
npm install update-electron-app
|
||||
```
|
||||
|
||||
Then, import the module and call it immediately in the main process.
|
||||
|
||||
```js title='main.js'
|
||||
require('update-electron-app')()
|
||||
```
|
||||
|
||||
And that is all it takes! Once your application is packaged, it will update itself for each new
|
||||
GitHub release that you publish.
|
||||
|
||||
## Summary
|
||||
|
||||
In this tutorial, we configured Electron Forge's GitHub Publisher to upload your app's
|
||||
distributables to GitHub releases. Since distributables cannot always be generated
|
||||
between platforms, we recommend setting up your building and publishing flow
|
||||
in a Continuous Integration pipeline if you do not have access to machines.
|
||||
|
||||
Electron applications can self-update by pointing the autoUpdater module to an update server feed.
|
||||
update.electronjs.org is a free update server provided by Electron for open-source applications
|
||||
published on GitHub releases. Configuring your Electron app to use this service is as easy as
|
||||
installing and importing the `update-electron-app` module.
|
||||
|
||||
If your application is not eligible for update.electronjs.org, you should instead deploy your
|
||||
own update server and configure the autoUpdater module yourself.
|
||||
|
||||
:::info 🌟 You're done!
|
||||
|
||||
From here, you have officially completed our tutorial to Electron. Feel free to explore the
|
||||
rest of our docs and happy developing! If you have questions, please stop by our community
|
||||
[Discord server].
|
||||
|
||||
:::
|
||||
|
||||
[autoupdater]: ../api/auto-updater.md
|
||||
[code-signed]: ./code-signing.md
|
||||
[discord server]: https://discord.com/invite/APGC3k5yaH
|
||||
[electron fiddle]: https://electronjs.org/fiddle
|
||||
[fiddle-build]: https://github.com/electron/fiddle/blob/master/.github/workflows/build.yaml
|
||||
[fiddle-forge-config]: https://github.com/electron/fiddle/blob/master/forge.config.js
|
||||
[github actions]: https://github.com/features/actions
|
||||
[github publisher]: https://www.electronforge.io/config/publishers/github
|
||||
[github releases]: https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository
|
||||
[git tag]: https://git-scm.com/book/en/v2/Git-Basics-Tagging
|
||||
[new-pat]: https://github.com/settings/tokens/new
|
||||
[publish command]: https://www.electronforge.io/cli#publish
|
||||
[publisher]: https://www.electronforge.io/config/publishers
|
||||
[`publishergithubconfig`]: https://js.electronforge.io/publisher/github/interfaces/publishergithubconfig
|
||||
[`update-electron-app`]: https://github.com/electron/update-electron-app
|
||||
[update-server]: ./updates.md
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
[prerequisites]: tutorial-1-prerequisites.md
|
||||
[building your first app]: tutorial-2-first-app.md
|
||||
[preload]: tutorial-3-preload.md
|
||||
[features]: tutorial-4-adding-features.md
|
||||
[packaging]: tutorial-5-packaging.md
|
||||
[updates]: tutorial-6-publishing-updating.md
|
||||
@@ -1,11 +1,16 @@
|
||||
# Updating Applications
|
||||
---
|
||||
title: 'Updating Applications'
|
||||
description: "There are several ways to update an Electron application. The easiest and officially supported one is taking advantage of the built-in Squirrel framework and Electron's autoUpdater module."
|
||||
slug: updates
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
There are several ways to update an Electron application. The easiest and
|
||||
officially supported one is taking advantage of the built-in
|
||||
There are several ways to provide automatic updates to your Electron application.
|
||||
The easiest and officially supported one is taking advantage of the built-in
|
||||
[Squirrel](https://github.com/Squirrel) framework and
|
||||
Electron's [autoUpdater](../api/auto-updater.md) module.
|
||||
|
||||
## Using `update.electronjs.org`
|
||||
## Using update.electronjs.org
|
||||
|
||||
The Electron team maintains [update.electronjs.org], a free and open-source
|
||||
webservice that Electron apps can use to self-update. The service is designed
|
||||
@@ -13,72 +18,77 @@ for Electron apps that meet the following criteria:
|
||||
|
||||
- App runs on macOS or Windows
|
||||
- App has a public GitHub repository
|
||||
- Builds are published to GitHub Releases
|
||||
- Builds are code-signed
|
||||
- Builds are published to [GitHub Releases][gh-releases]
|
||||
- Builds are [code-signed](./code-signing.md)
|
||||
|
||||
The easiest way to use this service is by installing [update-electron-app],
|
||||
a Node.js module preconfigured for use with update.electronjs.org.
|
||||
|
||||
Install the module:
|
||||
Install the module using your Node.js package manager of choice:
|
||||
|
||||
```sh
|
||||
```sh npm2yarn
|
||||
npm install update-electron-app
|
||||
```
|
||||
|
||||
Invoke the updater from your app's main process file:
|
||||
Then, invoke the updater from your app's main process file:
|
||||
|
||||
```js
|
||||
```js title="main.js"
|
||||
require('update-electron-app')()
|
||||
```
|
||||
|
||||
By default, this module will check for updates at app startup, then every ten
|
||||
minutes. When an update is found, it will automatically be downloaded in the background. When the download completes, a dialog is displayed allowing the user
|
||||
to restart the app.
|
||||
minutes. When an update is found, it will automatically be downloaded in the background.
|
||||
When the download completes, a dialog is displayed allowing the user to restart the app.
|
||||
|
||||
If you need to customize your configuration, you can
|
||||
[pass options to `update-electron-app`][update-electron-app]
|
||||
[pass options to update-electron-app][update-electron-app]
|
||||
or
|
||||
[use the update service directly][update.electronjs.org].
|
||||
|
||||
## Deploying an Update Server
|
||||
## Using other update services
|
||||
|
||||
If you're developing a private Electron application, or if you're not
|
||||
publishing releases to GitHub Releases, it may be necessary to run your own
|
||||
update server.
|
||||
|
||||
### Step 1: Deploying an update server
|
||||
|
||||
Depending on your needs, you can choose from one of these:
|
||||
|
||||
- [Hazel][hazel] – Update server for private or open-source apps which can be
|
||||
deployed for free on [Vercel][vercel]. It pulls from [GitHub Releases][gh-releases]
|
||||
and leverages the power of GitHub's CDN.
|
||||
deployed for free on [Vercel][vercel]. It pulls from [GitHub Releases][gh-releases]
|
||||
and leverages the power of GitHub's CDN.
|
||||
- [Nuts][nuts] – Also uses [GitHub Releases][gh-releases], but caches app
|
||||
updates on disk and supports private repositories.
|
||||
updates on disk and supports private repositories.
|
||||
- [electron-release-server][electron-release-server] – Provides a dashboard for
|
||||
handling releases and does not require releases to originate on GitHub.
|
||||
handling releases and does not require releases to originate on GitHub.
|
||||
- [Nucleus][nucleus] – A complete update server for Electron apps maintained by
|
||||
Atlassian. Supports multiple applications and channels; uses a static file store
|
||||
to minify server cost.
|
||||
Atlassian. Supports multiple applications and channels; uses a static file store
|
||||
to minify server cost.
|
||||
|
||||
## Implementing Updates in Your App
|
||||
Once you've deployed your update server, you can instrument your app code to receive and
|
||||
apply the updates with Electron's [autoUpdater] module.
|
||||
|
||||
Once you've deployed your update server, continue with importing the required
|
||||
modules in your code. The following code might vary for different server
|
||||
software, but it works like described when using
|
||||
[Hazel][hazel].
|
||||
### Step 2: Receiving updates in your app
|
||||
|
||||
**Important:** Please ensure that the code below will only be executed in
|
||||
your packaged app, and not in development. You can use
|
||||
[electron-is-dev](https://github.com/sindresorhus/electron-is-dev) to check for
|
||||
the environment.
|
||||
First, import the required modules in your main process code. The following code might
|
||||
vary for different server software, but it works like described when using [Hazel][hazel].
|
||||
|
||||
```javascript
|
||||
:::warning Check your execution environment!
|
||||
|
||||
Please ensure that the code below will only be executed in your packaged app, and not in development.
|
||||
You can use the [app.isPackaged](../api/app.md#appispackaged-readonly) API to check the environment.
|
||||
|
||||
:::
|
||||
|
||||
```javascript title='main.js'
|
||||
const { app, autoUpdater, dialog } = require('electron')
|
||||
```
|
||||
|
||||
Next, construct the URL of the update server and tell
|
||||
Next, construct the URL of the update server feed and tell
|
||||
[autoUpdater](../api/auto-updater.md) about it:
|
||||
|
||||
```javascript
|
||||
```javascript title='main.js'
|
||||
const server = 'https://your-deployment-url.com'
|
||||
const url = `${server}/update/${process.platform}/${app.getVersion()}`
|
||||
|
||||
@@ -87,32 +97,32 @@ autoUpdater.setFeedURL({ url })
|
||||
|
||||
As the final step, check for updates. The example below will check every minute:
|
||||
|
||||
```javascript
|
||||
```javascript title='main.js'
|
||||
setInterval(() => {
|
||||
autoUpdater.checkForUpdates()
|
||||
}, 60000)
|
||||
```
|
||||
|
||||
Once your application is [packaged](../tutorial/application-distribution.md),
|
||||
Once your application is [packaged](./application-distribution.md),
|
||||
it will receive an update for each new
|
||||
[GitHub Release](https://help.github.com/articles/creating-releases/) that you
|
||||
publish.
|
||||
|
||||
## Applying Updates
|
||||
### Step 3: Notifying users when updates are available
|
||||
|
||||
Now that you've configured the basic update mechanism for your application, you
|
||||
need to ensure that the user will get notified when there's an update. This
|
||||
can be achieved using the autoUpdater API
|
||||
[events](../api/auto-updater.md#events):
|
||||
can be achieved using the [autoUpdater API events](../api/auto-updater.md#events):
|
||||
|
||||
```javascript
|
||||
```javascript title="main.js"
|
||||
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
|
||||
const dialogOpts = {
|
||||
type: 'info',
|
||||
buttons: ['Restart', 'Later'],
|
||||
title: 'Application Update',
|
||||
message: process.platform === 'win32' ? releaseNotes : releaseName,
|
||||
detail: 'A new version has been downloaded. Restart the application to apply the updates.'
|
||||
detail:
|
||||
'A new version has been downloaded. Restart the application to apply the updates.',
|
||||
}
|
||||
|
||||
dialog.showMessageBox(dialogOpts).then((returnValue) => {
|
||||
@@ -125,16 +135,22 @@ Also make sure that errors are
|
||||
[being handled](../api/auto-updater.md#event-error). Here's an example
|
||||
for logging them to `stderr`:
|
||||
|
||||
```javascript
|
||||
autoUpdater.on('error', message => {
|
||||
```javascript title="main.js"
|
||||
autoUpdater.on('error', (message) => {
|
||||
console.error('There was a problem updating the application')
|
||||
console.error(message)
|
||||
})
|
||||
```
|
||||
|
||||
## Handling Updates Manually
|
||||
:::info Handling updates manually
|
||||
|
||||
Because the requests made by Auto Update aren't under your direct control, you may find situations that are difficult to handle (such as if the update server is behind authentication). The `url` field does support files, which means that with some effort, you can sidestep the server-communication aspect of the process. [Here's an example of how this could work](https://github.com/electron/electron/issues/5020#issuecomment-477636990).
|
||||
Because the requests made by autoUpdate aren't under your direct control, you may find situations
|
||||
that are difficult to handle (such as if the update server is behind authentication). The `url`
|
||||
field supports the `file://` protocol, which means that with some effort, you can sidestep the
|
||||
server-communication aspect of the process by loading your update from a local directory.
|
||||
[Here's an example of how this could work](https://github.com/electron/electron/issues/5020#issuecomment-477636990).
|
||||
|
||||
:::
|
||||
|
||||
[vercel]: https://vercel.com
|
||||
[hazel]: https://github.com/vercel/hazel
|
||||
|
||||
@@ -41,10 +41,9 @@ as quoted from [MSDN][msdn-jumplist]:
|
||||
> confuse the user who does not expect that portion of the destination list to
|
||||
> change.
|
||||
|
||||

|
||||

|
||||
|
||||
> NOTE: The screenshot above is an example of general tasks of
|
||||
Internet Explorer
|
||||
> NOTE: The screenshot above is an example of general tasks for Microsoft Edge
|
||||
|
||||
Unlike the dock menu in macOS which is a real menu, user tasks in Windows work
|
||||
like application shortcuts. For example, when a user clicks a task, the program
|
||||
@@ -109,7 +108,7 @@ As quoted from [MSDN][msdn-thumbnail]:
|
||||
> For example, Windows Media Player might offer standard media transport controls
|
||||
> such as play, pause, mute, and stop.
|
||||
|
||||

|
||||

|
||||
|
||||
> NOTE: The screenshot above is an example of thumbnail toolbar of Windows
|
||||
Media Player
|
||||
@@ -176,7 +175,7 @@ As quoted from [MSDN][msdn-icon-overlay]:
|
||||
> network status, messenger status, or new mail. The user should not be
|
||||
> presented with constantly changing overlays or animations.
|
||||
|
||||

|
||||

|
||||
|
||||
> NOTE: The screenshot above is an example of overlay on a taskbar button
|
||||
|
||||
|
||||
@@ -175,8 +175,10 @@ template("electron_paks") {
|
||||
source_patterns = [
|
||||
"${root_gen_dir}/chrome/platform_locale_settings_",
|
||||
"${root_gen_dir}/components/strings/components_strings_",
|
||||
"${root_gen_dir}/third_party/blink/public/strings/blink_accessibility_strings_",
|
||||
"${root_gen_dir}/third_party/blink/public/strings/blink_strings_",
|
||||
"${root_gen_dir}/device/bluetooth/strings/bluetooth_strings_",
|
||||
"${root_gen_dir}/extensions/strings/extensions_strings_",
|
||||
"${root_gen_dir}/services/strings/services_strings_",
|
||||
"${root_gen_dir}/ui/strings/app_locale_settings_",
|
||||
"${root_gen_dir}/ui/strings/ax_strings_",
|
||||
@@ -186,20 +188,22 @@ template("electron_paks") {
|
||||
"//chrome/app/resources:platform_locale_settings",
|
||||
"//components/strings:components_strings",
|
||||
"//device/bluetooth/strings",
|
||||
"//extensions/strings",
|
||||
"//services/strings",
|
||||
"//third_party/blink/public/strings",
|
||||
"//third_party/blink/public/strings:accessibility_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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user