mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
502 Commits
build/pres
...
10-x-y
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fc28e2296 | ||
|
|
fcdd18074f | ||
|
|
faa1655880 | ||
|
|
ebe509d24f | ||
|
|
ab3e65ae34 | ||
|
|
29d8cf5423 | ||
|
|
3ed3d28d70 | ||
|
|
030562e065 | ||
|
|
1adea52f3d | ||
|
|
9824bc06d5 | ||
|
|
382f1ec9e4 | ||
|
|
b0bbf47e0c | ||
|
|
770fff694a | ||
|
|
56b680713a | ||
|
|
118c2faa86 | ||
|
|
3cd06c9095 | ||
|
|
88ede25a99 | ||
|
|
d52c1ef201 | ||
|
|
40d0be9661 | ||
|
|
72f3c5e8ec | ||
|
|
882eb8a3ba | ||
|
|
c840550619 | ||
|
|
59c0c9fce0 | ||
|
|
1b8d60305b | ||
|
|
1f6e825a9f | ||
|
|
c9774944ba | ||
|
|
99a521ecbe | ||
|
|
d3152808bb | ||
|
|
3fe97b1b1b | ||
|
|
95d9d7ddfe | ||
|
|
5593485831 | ||
|
|
049b1d0817 | ||
|
|
a5e40fea7d | ||
|
|
840ff8d720 | ||
|
|
f8738fb355 | ||
|
|
16568d71e4 | ||
|
|
8f1074c204 | ||
|
|
0b6842d429 | ||
|
|
4f4c6a2161 | ||
|
|
95b81c16c4 | ||
|
|
bb913bc17b | ||
|
|
7c72a36b15 | ||
|
|
792d189241 | ||
|
|
602f65ab5d | ||
|
|
18d60df173 | ||
|
|
ce12429814 | ||
|
|
b44be57752 | ||
|
|
7d8616b2b7 | ||
|
|
35b0e35544 | ||
|
|
93b44837a2 | ||
|
|
e16d593fcb | ||
|
|
51f9712c8f | ||
|
|
36cdfef776 | ||
|
|
8920fd100e | ||
|
|
4142f4e74e | ||
|
|
ffd43c97f2 | ||
|
|
a576c92d4b | ||
|
|
9c3da1cb35 | ||
|
|
2e5c33a25b | ||
|
|
beca2c5c02 | ||
|
|
4b24e2b045 | ||
|
|
1f1ff0e51f | ||
|
|
e744ac042a | ||
|
|
12a9970969 | ||
|
|
bb915813d7 | ||
|
|
2e9a3d6f28 | ||
|
|
91c465dcea | ||
|
|
200e7294de | ||
|
|
c2cef0aa02 | ||
|
|
581b47582f | ||
|
|
59951f344b | ||
|
|
6e9db782c7 | ||
|
|
a64d0713cd | ||
|
|
e7d7c66636 | ||
|
|
c6f8625947 | ||
|
|
1c198eef50 | ||
|
|
dc664acab2 | ||
|
|
6b89037dea | ||
|
|
d3e828cc4e | ||
|
|
acabbf22fe | ||
|
|
ee95a258b3 | ||
|
|
072bec5d01 | ||
|
|
c3da53d3c0 | ||
|
|
2345ff0644 | ||
|
|
a217df4a9d | ||
|
|
4de0f99073 | ||
|
|
4f3b520516 | ||
|
|
4293389679 | ||
|
|
7c1335ec1c | ||
|
|
779efcfa11 | ||
|
|
bd08155093 | ||
|
|
f71c2c78dd | ||
|
|
5e30c0ae26 | ||
|
|
7966baff5a | ||
|
|
986d23d793 | ||
|
|
afb74be01a | ||
|
|
8068b39ddc | ||
|
|
e8ae6fe0d0 | ||
|
|
b5de6d9440 | ||
|
|
a2f777213d | ||
|
|
f916f172e0 | ||
|
|
6606b743c0 | ||
|
|
ee86f029d8 | ||
|
|
8baf1dc0e5 | ||
|
|
0827a06b1e | ||
|
|
2aec5c5df5 | ||
|
|
5483733b1b | ||
|
|
52f8f91931 | ||
|
|
227d6ead6d | ||
|
|
fb4cd68f93 | ||
|
|
7d3db3d7f8 | ||
|
|
9510e1f6e4 | ||
|
|
a396489101 | ||
|
|
b90f5435a9 | ||
|
|
13a0757acb | ||
|
|
a5a6f12e1d | ||
|
|
cef56e162f | ||
|
|
a73163d09a | ||
|
|
2e98e11364 | ||
|
|
0ead47ffea | ||
|
|
1897909a50 | ||
|
|
62b2243574 | ||
|
|
6e35f2b7dd | ||
|
|
c4bf95576c | ||
|
|
4005935937 | ||
|
|
31fa081da1 | ||
|
|
340b4a2c1e | ||
|
|
fd269ec973 | ||
|
|
d133ec709f | ||
|
|
2b76ac0848 | ||
|
|
726e3f9bb8 | ||
|
|
bc336e16ef | ||
|
|
1faf18f2d4 | ||
|
|
4a1e299053 | ||
|
|
ae1f1f2dfa | ||
|
|
fe4bc1d568 | ||
|
|
d6d9d954b4 | ||
|
|
2ee375c5bf | ||
|
|
c04ec2d332 | ||
|
|
4f9122647a | ||
|
|
846504af8e | ||
|
|
5d97320ba3 | ||
|
|
2aaa5438cd | ||
|
|
08da5ee22a | ||
|
|
f3a4b44662 | ||
|
|
424177164e | ||
|
|
079251f168 | ||
|
|
17054405d8 | ||
|
|
d1d8c9badd | ||
|
|
700c410ec3 | ||
|
|
d3f7ad2035 | ||
|
|
f5deaedfaa | ||
|
|
2717a48f30 | ||
|
|
fea41c6f6d | ||
|
|
d58bfdcdfd | ||
|
|
d0451832ed | ||
|
|
22481aa347 | ||
|
|
7b0bb0b637 | ||
|
|
36f8e9daa2 | ||
|
|
4594af595e | ||
|
|
0bbd268eb4 | ||
|
|
47b9207e6d | ||
|
|
846412cdf1 | ||
|
|
b77e48a2c7 | ||
|
|
87d98480fa | ||
|
|
6d468cd9b5 | ||
|
|
38e585434f | ||
|
|
5481d27bcd | ||
|
|
135133e391 | ||
|
|
ad8de076e3 | ||
|
|
5bad2d106c | ||
|
|
883b089e0f | ||
|
|
d0abffc1e7 | ||
|
|
e24e77f4a2 | ||
|
|
9562a92c5d | ||
|
|
4efe747847 | ||
|
|
47f015f1e8 | ||
|
|
5604037294 | ||
|
|
f6a3ba5d67 | ||
|
|
34fe161bdd | ||
|
|
e1bf7b9d8b | ||
|
|
5de766deb5 | ||
|
|
70e41bcf43 | ||
|
|
f7a61c4592 | ||
|
|
b19c549511 | ||
|
|
de14497f1c | ||
|
|
570f9827ce | ||
|
|
9900e697b5 | ||
|
|
c6979ca421 | ||
|
|
ace3f9d3e1 | ||
|
|
7bd2f0db23 | ||
|
|
83db340eb3 | ||
|
|
17d08c1557 | ||
|
|
66e548333f | ||
|
|
7558b5878b | ||
|
|
3ad830c804 | ||
|
|
2460b02e48 | ||
|
|
9012c3bb8b | ||
|
|
90d72684fc | ||
|
|
529fbf53e1 | ||
|
|
4ef5c2666e | ||
|
|
4aa4d1914b | ||
|
|
16681be8fd | ||
|
|
0aef4d6a8d | ||
|
|
ae3c79d6ce | ||
|
|
fee2655061 | ||
|
|
a3c1866581 | ||
|
|
38f0916eea | ||
|
|
6543acce1d | ||
|
|
15db70d661 | ||
|
|
1b32fd2a9b | ||
|
|
6147bd77ac | ||
|
|
ffd1e9bad2 | ||
|
|
682b382aa3 | ||
|
|
3ad59397ae | ||
|
|
6502e4e9cb | ||
|
|
d5119c499c | ||
|
|
0fa84aef3b | ||
|
|
fe28c5ba06 | ||
|
|
9242fff9c2 | ||
|
|
a538755595 | ||
|
|
139cb2dea5 | ||
|
|
831e84504d | ||
|
|
ccbf615da0 | ||
|
|
d8fd2dca6d | ||
|
|
86d6aa75ad | ||
|
|
99df3b8147 | ||
|
|
776f76c6f5 | ||
|
|
1df0ea58d5 | ||
|
|
e50545db30 | ||
|
|
4a312e9c6b | ||
|
|
0992fb35ea | ||
|
|
904404d3c4 | ||
|
|
fa491d7e4b | ||
|
|
8a052c5537 | ||
|
|
b3d89bd3bf | ||
|
|
28f4c546ca | ||
|
|
aac0012c8c | ||
|
|
7e74f2ca1e | ||
|
|
fd3ce5f63f | ||
|
|
62536dc907 | ||
|
|
b679813fc5 | ||
|
|
38d126fb5c | ||
|
|
04fdfe610c | ||
|
|
ac917b5573 | ||
|
|
fb482ae4cb | ||
|
|
13722f83e3 | ||
|
|
ccaea19e32 | ||
|
|
25674a40bd | ||
|
|
fe94fd029f | ||
|
|
f1359e6b12 | ||
|
|
f01defa58c | ||
|
|
11847e78a8 | ||
|
|
29ca849382 | ||
|
|
624ea4b694 | ||
|
|
56a764d510 | ||
|
|
88af747a5b | ||
|
|
7ae4b2b559 | ||
|
|
244f405e6a | ||
|
|
c8f9d0908a | ||
|
|
9f21accfc2 | ||
|
|
93677081f0 | ||
|
|
455098db90 | ||
|
|
d4239bb42e | ||
|
|
de0ddd5b56 | ||
|
|
cdfbcb39f2 | ||
|
|
21afda3679 | ||
|
|
37bcb093e7 | ||
|
|
4a0f2bede2 | ||
|
|
e964c1ed7b | ||
|
|
6fe6dffe93 | ||
|
|
0b75053fdc | ||
|
|
894d41ef5a | ||
|
|
a99256da8c | ||
|
|
430a6ada64 | ||
|
|
f82c375698 | ||
|
|
113c65f32f | ||
|
|
a42a529236 | ||
|
|
9582f0b457 | ||
|
|
a230e31b31 | ||
|
|
63688e8649 | ||
|
|
24691a4e0f | ||
|
|
a3ac80640d | ||
|
|
552ec2267b | ||
|
|
fc915754f6 | ||
|
|
80ef3c7c84 | ||
|
|
21a46bc0eb | ||
|
|
7fc5c468e9 | ||
|
|
fbd99fbed1 | ||
|
|
d563c79521 | ||
|
|
2ccfb825df | ||
|
|
88d7bdc8c8 | ||
|
|
c6eeff8055 | ||
|
|
f99afa4d58 | ||
|
|
303b420200 | ||
|
|
fa3652a14f | ||
|
|
fdbd2439a6 | ||
|
|
ac3e10c88c | ||
|
|
5067b012d4 | ||
|
|
ae80f43675 | ||
|
|
9b6b09216b | ||
|
|
34a246e3ce | ||
|
|
0dea6fa7f0 | ||
|
|
61dc1c88fd | ||
|
|
c63327f9b2 | ||
|
|
615dce3275 | ||
|
|
4ea6af64a7 | ||
|
|
66b6789c50 | ||
|
|
749b134e09 | ||
|
|
1c3ebfdc30 | ||
|
|
2206330795 | ||
|
|
10de79126a | ||
|
|
a42fa5158f | ||
|
|
f2c6053111 | ||
|
|
34a321f46b | ||
|
|
deb78453c0 | ||
|
|
d73b67f386 | ||
|
|
0b834877fe | ||
|
|
4df5ecdf82 | ||
|
|
a980ad5645 | ||
|
|
7cc0cb4331 | ||
|
|
414aa3111b | ||
|
|
5753370c8d | ||
|
|
606919f701 | ||
|
|
1861392561 | ||
|
|
e492b88f9f | ||
|
|
da5eac885d | ||
|
|
44ecd34289 | ||
|
|
c5b5ca50a6 | ||
|
|
4b7b3dc4f2 | ||
|
|
4a43487b39 | ||
|
|
a799860d7e | ||
|
|
93727d6a11 | ||
|
|
207fbecddf | ||
|
|
588ae53970 | ||
|
|
8a8fe090ae | ||
|
|
711bab1950 | ||
|
|
50046f8df6 | ||
|
|
9193d35769 | ||
|
|
8191a8418f | ||
|
|
f4600bdfdf | ||
|
|
7fd8e6a14e | ||
|
|
a1abe6b64c | ||
|
|
a6f22059af | ||
|
|
3089bf939f | ||
|
|
180204887a | ||
|
|
af59f68281 | ||
|
|
e9c9a6f177 | ||
|
|
6582017231 | ||
|
|
4e82a50883 | ||
|
|
7079304a6c | ||
|
|
8fb28051a4 | ||
|
|
72901f9d91 | ||
|
|
838e00a523 | ||
|
|
596136ae99 | ||
|
|
8e1daa4449 | ||
|
|
5c19e983f9 | ||
|
|
cf5be544b6 | ||
|
|
28a9fb8ea2 | ||
|
|
cf935eb81b | ||
|
|
f47f8df7f9 | ||
|
|
d77f4f62fd | ||
|
|
276d17a063 | ||
|
|
f6ddfd70b3 | ||
|
|
04f652a53b | ||
|
|
04c5f4acac | ||
|
|
ca15aa70d6 | ||
|
|
96bc80ace7 | ||
|
|
e3cf1ab030 | ||
|
|
04e3a95b85 | ||
|
|
58045d85c8 | ||
|
|
08fc9dfc40 | ||
|
|
5fb3e0359d | ||
|
|
325444e1c8 | ||
|
|
bc4884788c | ||
|
|
0a766acc73 | ||
|
|
578aef4714 | ||
|
|
c9c89f9c8e | ||
|
|
9d90a994cf | ||
|
|
3cfdc086bb | ||
|
|
6c04533fca | ||
|
|
99f1d7e57a | ||
|
|
009105db4f | ||
|
|
b2f09a1469 | ||
|
|
74212577e5 | ||
|
|
8da4e299c6 | ||
|
|
b2ffded4a9 | ||
|
|
039a8ab49b | ||
|
|
1b4b4fddaa | ||
|
|
fdde45379e | ||
|
|
9462e9a3ed | ||
|
|
d08e31c6b4 | ||
|
|
b2449f3ce1 | ||
|
|
683c0c0491 | ||
|
|
91a6399c22 | ||
|
|
799a04a4c0 | ||
|
|
82092471e4 | ||
|
|
39a931968c | ||
|
|
bd7f6a9090 | ||
|
|
2d747acd67 | ||
|
|
8371e83a9d | ||
|
|
22c804a4ad | ||
|
|
5481ddf9df | ||
|
|
4c596ab969 | ||
|
|
328c5c7b46 | ||
|
|
5b8d4240d6 | ||
|
|
d52412dea7 | ||
|
|
39edbd6af4 | ||
|
|
30db185060 | ||
|
|
c804212426 | ||
|
|
7a5b18b0d6 | ||
|
|
d608a30015 | ||
|
|
74efe8d834 | ||
|
|
3283211a15 | ||
|
|
d4a6affa4b | ||
|
|
73e13ab6d6 | ||
|
|
c32c69604a | ||
|
|
2761be6467 | ||
|
|
30cb2b134b | ||
|
|
48cd3eeced | ||
|
|
831b6fa227 | ||
|
|
91ce51cfb3 | ||
|
|
bf1870facc | ||
|
|
39bc7c82a6 | ||
|
|
991d982622 | ||
|
|
195662ead0 | ||
|
|
d580cc1578 | ||
|
|
d8de43f534 | ||
|
|
c48a6b48c9 | ||
|
|
d701c292a0 | ||
|
|
19e7af9841 | ||
|
|
86e4a96f45 | ||
|
|
e059ae7bd6 | ||
|
|
fb292c26d5 | ||
|
|
0e0dd6460f | ||
|
|
b464589143 | ||
|
|
ee372c152a | ||
|
|
53bdc4a71b | ||
|
|
ab0960ecd9 | ||
|
|
29c9c80c89 | ||
|
|
72f2dad3a1 | ||
|
|
64cdfda810 | ||
|
|
9f8f82af00 | ||
|
|
306d76b317 | ||
|
|
097c501cf5 | ||
|
|
d4bc4e1d4c | ||
|
|
0c861dc83e | ||
|
|
57b766aa82 | ||
|
|
4b8295a24d | ||
|
|
710199c308 | ||
|
|
c2d9cde38f | ||
|
|
fbaca68bd0 | ||
|
|
ee9f95df30 | ||
|
|
9df936d941 | ||
|
|
baa2940488 | ||
|
|
25879ba929 | ||
|
|
34b04e5fbb | ||
|
|
710ac2a5a8 | ||
|
|
1f0d2594bd | ||
|
|
656d9e7490 | ||
|
|
5bf938f899 | ||
|
|
7759048136 | ||
|
|
321c1c1075 | ||
|
|
d69d1bbf20 | ||
|
|
f3dd997dbd | ||
|
|
faf7951439 | ||
|
|
3087492994 | ||
|
|
f7e4377ee8 | ||
|
|
ef288a6ae2 | ||
|
|
7797835f93 | ||
|
|
9572209e91 | ||
|
|
3602216e6c | ||
|
|
c29382b6d0 | ||
|
|
a8fc41d8b3 | ||
|
|
9ea42da40e | ||
|
|
87cd20b9e9 | ||
|
|
79acd3e0ef | ||
|
|
67be46986c | ||
|
|
d4001c1787 | ||
|
|
eeaad9c6ab | ||
|
|
cc0c7632ac | ||
|
|
12ea1c0c41 | ||
|
|
9d2aa93581 | ||
|
|
cee9e6f0d0 | ||
|
|
eb93acc463 | ||
|
|
241e74c098 | ||
|
|
c0183d15af | ||
|
|
4fe7c9ac24 | ||
|
|
50efa847a5 | ||
|
|
c2354d44ea | ||
|
|
7709e600c6 | ||
|
|
0962c1bd74 | ||
|
|
471f80521d | ||
|
|
1fb11e1e76 | ||
|
|
f8508b3c18 | ||
|
|
95e3853b77 | ||
|
|
9de5ede1fb | ||
|
|
05efbbcdd5 | ||
|
|
2789f32efb | ||
|
|
4c8b884998 | ||
|
|
03ddd2d7af | ||
|
|
c141b1a906 |
@@ -61,7 +61,7 @@ parameters:
|
||||
# Build machines configs.
|
||||
docker-image: &docker-image
|
||||
docker:
|
||||
- image: electronjs/build:d09fd95029bd8c1c73069888231b29688ef385ed
|
||||
- image: electron.azurecr.io/build:4cec2c5ab66765caa724e37bae2bffb9b29722a5
|
||||
|
||||
machine-linux-medium: &machine-linux-medium
|
||||
<<: *docker-image
|
||||
@@ -94,6 +94,7 @@ env-release-build: &env-release-build
|
||||
STRIP_BINARIES: true
|
||||
GENERATE_SYMBOLS: true
|
||||
CHECK_DIST_MANIFEST: '1'
|
||||
IS_RELEASE: true
|
||||
|
||||
env-headless-testing: &env-headless-testing
|
||||
DISPLAY: ':99.0'
|
||||
@@ -134,9 +135,6 @@ env-mas: &env-mas
|
||||
MAS_BUILD: 'true'
|
||||
|
||||
# Misc build configuration options.
|
||||
env-enable-sccache: &env-enable-sccache
|
||||
USE_SCCACHE: true
|
||||
|
||||
env-send-slack-notifications: &env-send-slack-notifications
|
||||
NOTIFY_SLACK: true
|
||||
|
||||
@@ -232,23 +230,34 @@ step-gclient-sync: &step-gclient-sync
|
||||
"$CIRCLE_REPOSITORY_URL"
|
||||
|
||||
ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 gclient sync --with_branch_heads --with_tags
|
||||
# Re-export all the patches to check if there were changes.
|
||||
python src/electron/script/export_all_patches.py src/electron/patches/config.json
|
||||
cd src/electron
|
||||
git update-index --refresh || true
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
# There are changes to the patches. Make a git commit with the updated patches
|
||||
git add patches
|
||||
GIT_COMMITTER_NAME="Electron Bot" GIT_COMMITTER_EMAIL="anonymous@electronjs.org" git commit -m "update patches" --author="Electron Bot <anonymous@electronjs.org>"
|
||||
# Export it
|
||||
mkdir -p ../../patches
|
||||
git format-patch -1 --stdout --keep-subject --no-stat --full-index > ../../patches/update-patches.patch
|
||||
echo
|
||||
echo "======================================================================"
|
||||
echo "There were changes to the patches when applying."
|
||||
echo "Check the CI artifacts for a patch you can apply to fix it."
|
||||
echo "======================================================================"
|
||||
exit 1
|
||||
if [ "$IS_RELEASE" != "true" ]; then
|
||||
# Re-export all the patches to check if there were changes.
|
||||
python src/electron/script/export_all_patches.py src/electron/patches/config.json
|
||||
cd src/electron
|
||||
git update-index --refresh || true
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
# There are changes to the patches. Make a git commit with the updated patches
|
||||
git add patches
|
||||
GIT_COMMITTER_NAME="PatchUp" GIT_COMMITTER_EMAIL="73610968+patchup[bot]@users.noreply.github.com" git commit -m "chore: update patches" --author="PatchUp <73610968+patchup[bot]@users.noreply.github.com>"
|
||||
# Export it
|
||||
mkdir -p ../../patches
|
||||
git format-patch -1 --stdout --keep-subject --no-stat --full-index > ../../patches/update-patches.patch
|
||||
if (node ./script/push-patch.js 2> /dev/null > /dev/null); then
|
||||
echo
|
||||
echo "======================================================================"
|
||||
echo "Changes to the patches when applying, we have auto-pushed the diff to the current branch"
|
||||
echo "A new CI job will kick off shortly"
|
||||
echo "======================================================================"
|
||||
exit 1
|
||||
else
|
||||
echo
|
||||
echo "======================================================================"
|
||||
echo "There were changes to the patches when applying."
|
||||
echo "Check the CI artifacts for a patch you can apply to fix it."
|
||||
echo "======================================================================"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -259,26 +268,14 @@ step-setup-env-for-build: &step-setup-env-for-build
|
||||
# To find `gn` executable.
|
||||
echo 'export CHROMIUM_BUILDTOOLS_PATH="'"$PWD"'/src/buildtools"' >> $BASH_ENV
|
||||
|
||||
if [ "$USE_SCCACHE" == "true" ]; then
|
||||
# https://github.com/mozilla/sccache
|
||||
SCCACHE_PATH="$PWD/src/electron/external_binaries/sccache"
|
||||
echo 'export SCCACHE_PATH="'"$SCCACHE_PATH"'"' >> $BASH_ENV
|
||||
if [ "$CIRCLE_PR_NUMBER" != "" ]; then
|
||||
#if building a fork set readonly access to sccache
|
||||
echo 'export SCCACHE_BUCKET="electronjs-sccache-ci"' >> $BASH_ENV
|
||||
echo 'export SCCACHE_TWO_TIER=true' >> $BASH_ENV
|
||||
fi
|
||||
fi
|
||||
|
||||
step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
run:
|
||||
name: Setup Goma
|
||||
command: |
|
||||
echo 'export USE_GOMA=true' >> $BASH_ENV
|
||||
if [ "`uname`" == "Linux" ]; then
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
|
||||
else
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=25' >> $BASH_ENV
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
echo 'ulimit -n 10000' >> $BASH_ENV
|
||||
echo 'sudo launchctl limit maxfiles 65536 200000' >> $BASH_ENV
|
||||
fi
|
||||
if [ ! -z "$RAW_GOMA_AUTH" ]; then
|
||||
echo $RAW_GOMA_AUTH > ~/.goma_oauth2_config
|
||||
@@ -287,24 +284,27 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
cd build-tools
|
||||
npm install
|
||||
mkdir third_party
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare()"
|
||||
node -e "require('./src/utils/goma.js').ensure()"
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
third_party/goma/goma_ctl.py ensure_start
|
||||
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
|
||||
echo 'export LOCAL_GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
|
||||
echo 'export GOMA_FALLBACK_ON_AUTH_FAILURE=true' >> $BASH_ENV
|
||||
cd ..
|
||||
|
||||
step-restore-brew-cache: &step-restore-brew-cache
|
||||
restore_cache:
|
||||
paths:
|
||||
- /usr/local/Homebrew
|
||||
- /usr/local/Cellar/gnu-tar
|
||||
- /usr/local/bin/gtar
|
||||
keys:
|
||||
- v1-brew-cache-{{ arch }}
|
||||
- v4-brew-cache-{{ arch }}
|
||||
|
||||
step-save-brew-cache: &step-save-brew-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- /usr/local/Homebrew
|
||||
key: v1-brew-cache-{{ arch }}
|
||||
- /usr/local/Cellar/gnu-tar
|
||||
- /usr/local/bin/gtar
|
||||
key: v4-brew-cache-{{ arch }}
|
||||
name: Persisting brew cache
|
||||
|
||||
step-get-more-space-on-mac: &step-get-more-space-on-mac
|
||||
@@ -313,12 +313,15 @@ step-get-more-space-on-mac: &step-get-more-space-on-mac
|
||||
command: |
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
sudo rm -rf /Library/Developer/CoreSimulator
|
||||
sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform
|
||||
sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
|
||||
sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform
|
||||
sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform
|
||||
sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform
|
||||
sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform
|
||||
sudo rm -rf $(xcode-select -p)/Platforms/AppleTVOS.platform
|
||||
sudo rm -rf $(xcode-select -p)/Platforms/iPhoneOS.platform
|
||||
sudo rm -rf $(xcode-select -p)/Platforms/WatchOS.platform
|
||||
sudo rm -rf $(xcode-select -p)/Platforms/WatchSimulator.platform
|
||||
sudo rm -rf $(xcode-select -p)/Platforms/AppleTVSimulator.platform
|
||||
sudo rm -rf $(xcode-select -p)/Platforms/iPhoneSimulator.platform
|
||||
sudo rm -rf ~/.rubies
|
||||
sudo rm -rf ~/Library/Caches/Homebrew
|
||||
sudo rm -rf /usr/local/Homebrew
|
||||
fi
|
||||
|
||||
# On macOS delete all .git directories under src/ expect for
|
||||
@@ -377,8 +380,10 @@ step-install-gnutar-on-mac: &step-install-gnutar-on-mac
|
||||
name: Install gnu-tar on macos
|
||||
command: |
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
brew update
|
||||
brew install gnu-tar
|
||||
if [ ! -d /usr/local/Cellar/gnu-tar/ ]; then
|
||||
brew update
|
||||
brew install gnu-tar
|
||||
fi
|
||||
ln -fs /usr/local/bin/gtar /usr/local/bin/tar
|
||||
fi
|
||||
|
||||
@@ -387,11 +392,7 @@ step-gn-gen-default: &step-gn-gen-default
|
||||
name: Default GN gen
|
||||
command: |
|
||||
cd src
|
||||
if [ "$USE_GOMA" == "true" ]; then
|
||||
gn gen out/Default --args="import(\"$GN_CONFIG\") import(\"$GN_GOMA_FILE\") $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
else
|
||||
gn gen out/Default --args="import(\"$GN_CONFIG\") cc_wrapper=\"$SCCACHE_PATH\" $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
fi
|
||||
gn gen out/Default --args="import(\"$GN_CONFIG\") import(\"$GN_GOMA_FILE\") $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
|
||||
step-gn-check: &step-gn-check
|
||||
run:
|
||||
@@ -418,6 +419,7 @@ step-electron-build: &step-electron-build
|
||||
fi
|
||||
cd src
|
||||
ninja -C out/Default electron -j $NUMBER_OF_NINJA_PROCESSES
|
||||
node electron/script/check-symlinks.js
|
||||
|
||||
step-native-unittests-build: &step-native-unittests-build
|
||||
run:
|
||||
@@ -487,11 +489,7 @@ step-electron-maybe-chromedriver-gn-gen: &step-electron-maybe-chromedriver-gn-ge
|
||||
command: |
|
||||
cd src
|
||||
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
if [ "$USE_GOMA" == "true" ]; then
|
||||
gn gen out/chromedriver --args="import(\"$GN_CONFIG\") import(\"$GN_GOMA_FILE\") is_component_ffmpeg=false proprietary_codecs=false $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
else
|
||||
gn gen out/chromedriver --args="import(\"$GN_CONFIG\") cc_wrapper=\"$SCCACHE_PATH\" is_component_ffmpeg=false proprietary_codecs=false $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
fi
|
||||
gn gen out/chromedriver --args="import(\"$GN_CONFIG\") import(\"$GN_GOMA_FILE\") is_component_ffmpeg=false proprietary_codecs=false $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
fi
|
||||
|
||||
step-electron-chromedriver-build: &step-electron-chromedriver-build
|
||||
@@ -546,10 +544,10 @@ step-electron-publish: &step-electron-publish
|
||||
cd src/electron
|
||||
if [ "$UPLOAD_TO_S3" == "1" ]; then
|
||||
echo 'Uploading Electron release distribution to S3'
|
||||
script/release/uploaders/upload.py --upload_to_s3
|
||||
script/release/uploaders/upload.py --verbose --upload_to_s3
|
||||
else
|
||||
echo 'Uploading Electron release distribution to Github releases'
|
||||
script/release/uploaders/upload.py
|
||||
script/release/uploaders/upload.py --verbose
|
||||
fi
|
||||
|
||||
step-persist-data-for-tests: &step-persist-data-for-tests
|
||||
@@ -602,11 +600,7 @@ step-ffmpeg-gn-gen: &step-ffmpeg-gn-gen
|
||||
name: ffmpeg GN gen
|
||||
command: |
|
||||
cd src
|
||||
if [ "$USE_GOMA" == "true" ]; then
|
||||
gn gen out/ffmpeg --args="import(\"//electron/build/args/ffmpeg.gn\") import(\"$GN_GOMA_FILE\") $GN_EXTRA_ARGS"
|
||||
else
|
||||
gn gen out/ffmpeg --args="import(\"//electron/build/args/ffmpeg.gn\") cc_wrapper=\"$SCCACHE_PATH\" $GN_EXTRA_ARGS"
|
||||
fi
|
||||
gn gen out/ffmpeg --args="import(\"//electron/build/args/ffmpeg.gn\") import(\"$GN_GOMA_FILE\") $GN_EXTRA_ARGS"
|
||||
|
||||
step-ffmpeg-build: &step-ffmpeg-build
|
||||
run:
|
||||
@@ -649,16 +643,17 @@ step-setup-linux-for-headless-testing: &step-setup-linux-for-headless-testing
|
||||
sh -e /etc/init.d/xvfb start
|
||||
fi
|
||||
|
||||
step-show-sccache-stats: &step-show-sccache-stats
|
||||
step-show-goma-stats: &step-show-goma-stats
|
||||
run:
|
||||
name: Check sccache/goma stats after build
|
||||
shell: /bin/bash
|
||||
name: Check goma stats after build
|
||||
command: |
|
||||
if [ "$SCCACHE_PATH" != "" ]; then
|
||||
$SCCACHE_PATH -s
|
||||
fi
|
||||
if [ "$USE_GOMA" == "true" ]; then
|
||||
$LOCAL_GOMA_DIR/goma_ctl.py stat
|
||||
fi
|
||||
set +e
|
||||
set +o pipefail
|
||||
$LOCAL_GOMA_DIR/goma_ctl.py stat
|
||||
$LOCAL_GOMA_DIR/diagnose_goma_log.py
|
||||
true
|
||||
when: always
|
||||
|
||||
step-mksnapshot-build: &step-mksnapshot-build
|
||||
run:
|
||||
@@ -706,12 +701,11 @@ step-hunspell-store: &step-hunspell-store
|
||||
step-maybe-generate-breakpad-symbols: &step-maybe-generate-breakpad-symbols
|
||||
run:
|
||||
name: Generate breakpad symbols
|
||||
no_output_timeout: 30m
|
||||
command: |
|
||||
if [ "$GENERATE_SYMBOLS" == "true" ]; then
|
||||
cd src
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
cd out/Default/breakpad_symbols
|
||||
find . -name \*.sym -print0 | xargs -0 npx @sentry/cli@1.51.1 difutil bundle-sources
|
||||
fi
|
||||
|
||||
step-maybe-zip-symbols: &step-maybe-zip-symbols
|
||||
@@ -786,6 +780,8 @@ step-ninja-summary: &step-ninja-summary
|
||||
run:
|
||||
name: Print ninja summary
|
||||
command: |
|
||||
set +e
|
||||
set +o pipefail
|
||||
python depot_tools/post_build_ninja_summary.py -C src/out/Default
|
||||
|
||||
step-ninja-report: &step-ninja-report
|
||||
@@ -830,7 +826,7 @@ step-restore-out-cache: &step-restore-out-cache
|
||||
paths:
|
||||
- ./src/out/Default
|
||||
keys:
|
||||
- v7-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
|
||||
- v8-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
|
||||
name: Restoring out cache
|
||||
|
||||
step-set-git-cache-path: &step-set-git-cache-path
|
||||
@@ -854,7 +850,7 @@ step-save-out-cache: &step-save-out-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- ./src/out/Default
|
||||
key: v7-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
|
||||
key: v8-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
|
||||
name: Persisting out cache
|
||||
|
||||
step-run-electron-only-hooks: &step-run-electron-only-hooks
|
||||
@@ -990,7 +986,6 @@ steps-checkout-and-save-cache: &steps-checkout-and-save-cache
|
||||
- *step-maybe-early-exit-doc-only-change
|
||||
- *step-depot-tools-get
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-restore-brew-cache
|
||||
- *step-get-more-space-on-mac
|
||||
- *step-install-gnutar-on-mac
|
||||
|
||||
@@ -1029,6 +1024,7 @@ steps-electron-gn-check: &steps-electron-gn-check
|
||||
- *step-maybe-early-exit-doc-only-change
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-setup-env-for-build
|
||||
- *step-setup-goma-for-build
|
||||
- *step-gn-gen-default
|
||||
- *step-gn-check
|
||||
|
||||
@@ -1041,8 +1037,8 @@ steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-cha
|
||||
- *step-depot-tools-get
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-restore-brew-cache
|
||||
- *step-get-more-space-on-mac
|
||||
- *step-install-gnutar-on-mac
|
||||
- *step-get-more-space-on-mac
|
||||
- *step-generate-deps-hash
|
||||
- *step-touch-sync-done
|
||||
- maybe-restore-portaled-src-cache
|
||||
@@ -1062,6 +1058,7 @@ steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-cha
|
||||
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-setup-env-for-build
|
||||
- *step-setup-goma-for-build
|
||||
- *step-restore-brew-cache
|
||||
- *step-get-more-space-on-mac
|
||||
- *step-install-npm-deps-on-mac
|
||||
@@ -1071,26 +1068,13 @@ steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-cha
|
||||
#Compile ts/js to verify doc change didn't break anything
|
||||
- *step-ts-compile
|
||||
|
||||
steps-chromedriver-build: &steps-chromedriver-build
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-setup-env-for-build
|
||||
- *step-fix-sync-on-mac
|
||||
|
||||
- *step-electron-maybe-chromedriver-gn-gen
|
||||
- *step-electron-chromedriver-build
|
||||
- *step-electron-chromedriver-store
|
||||
|
||||
- *step-maybe-notify-slack-failure
|
||||
|
||||
steps-native-tests: &steps-native-tests
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-setup-env-for-build
|
||||
- *step-setup-goma-for-build
|
||||
- *step-gn-gen-default
|
||||
|
||||
- run:
|
||||
@@ -1098,7 +1082,7 @@ steps-native-tests: &steps-native-tests
|
||||
command: |
|
||||
cd src
|
||||
ninja -C out/Default $BUILD_TARGET
|
||||
- *step-show-sccache-stats
|
||||
- *step-show-goma-stats
|
||||
|
||||
- *step-setup-linux-for-headless-testing
|
||||
- run:
|
||||
@@ -1392,7 +1376,7 @@ commands:
|
||||
- *step-nodejs-headers-build
|
||||
- *step-nodejs-headers-store
|
||||
|
||||
- *step-show-sccache-stats
|
||||
- *step-show-goma-stats
|
||||
|
||||
# mksnapshot
|
||||
- *step-mksnapshot-build
|
||||
@@ -1480,13 +1464,14 @@ commands:
|
||||
- *step-gclient-sync
|
||||
- *step-delete-git-directories
|
||||
- *step-minimize-workspace-size-from-checkout
|
||||
- *step-fix-sync-on-mac
|
||||
- *step-fix-sync-on-mac
|
||||
- *step-setup-env-for-build
|
||||
- *step-setup-goma-for-build
|
||||
- *step-gn-gen-default
|
||||
|
||||
# Electron app
|
||||
- *step-electron-build
|
||||
- *step-show-sccache-stats
|
||||
- *step-show-goma-stats
|
||||
- *step-maybe-generate-breakpad-symbols
|
||||
- *step-maybe-electron-dist-strip
|
||||
- *step-electron-dist-build
|
||||
@@ -1670,14 +1655,6 @@ jobs:
|
||||
<<: *env-testing-build
|
||||
<<: *steps-electron-gn-check
|
||||
|
||||
linux-x64-chromedriver:
|
||||
<<: *machine-linux-medium
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *env-release-build
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-chromedriver-build
|
||||
|
||||
linux-x64-release:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
@@ -1697,8 +1674,8 @@ jobs:
|
||||
<<: *env-linux-2xlarge-release
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
- electron-publish:
|
||||
attach: false
|
||||
@@ -1709,8 +1686,8 @@ jobs:
|
||||
environment:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
- electron-publish:
|
||||
attach: true
|
||||
@@ -1730,15 +1707,6 @@ jobs:
|
||||
checkout: true
|
||||
use-out-cache: false
|
||||
|
||||
linux-ia32-chromedriver:
|
||||
<<: *machine-linux-medium
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *env-ia32
|
||||
<<: *env-release-build
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-chromedriver-build
|
||||
|
||||
linux-ia32-release:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
@@ -1760,9 +1728,9 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
|
||||
<<: *env-ia32
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-32bit-release
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
- electron-publish:
|
||||
attach: false
|
||||
@@ -1774,9 +1742,9 @@ jobs:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-ia32
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-32bit-release
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
- electron-publish:
|
||||
attach: true
|
||||
@@ -1797,15 +1765,6 @@ jobs:
|
||||
checkout: true
|
||||
use-out-cache: false
|
||||
|
||||
linux-arm-chromedriver:
|
||||
<<: *machine-linux-medium
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *env-arm
|
||||
<<: *env-release-build
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-chromedriver-build
|
||||
|
||||
linux-arm-release:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
@@ -1826,10 +1785,10 @@ jobs:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-arm
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-32bit-release
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_boto=True --custom-var=checkout_requests=True'
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
- electron-publish:
|
||||
attach: false
|
||||
@@ -1841,9 +1800,9 @@ jobs:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-arm
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-32bit-release
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
- electron-publish:
|
||||
attach: true
|
||||
@@ -1872,15 +1831,6 @@ jobs:
|
||||
<<: *env-testing-build
|
||||
<<: *steps-electron-gn-check
|
||||
|
||||
linux-arm64-chromedriver:
|
||||
<<: *machine-linux-medium
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *env-arm64
|
||||
<<: *env-release-build
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-chromedriver-build
|
||||
|
||||
linux-arm64-release:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
@@ -1901,9 +1851,9 @@ jobs:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-arm64
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm64=True --custom-var=checkout_boto=True --custom-var=checkout_requests=True'
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
- electron-publish:
|
||||
attach: false
|
||||
@@ -1915,8 +1865,8 @@ jobs:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-arm64
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
- electron-publish:
|
||||
attach: true
|
||||
@@ -1944,14 +1894,6 @@ jobs:
|
||||
<<: *env-testing-build
|
||||
<<: *steps-electron-gn-check
|
||||
|
||||
osx-chromedriver:
|
||||
<<: *machine-mac
|
||||
environment:
|
||||
<<: *env-machine-mac
|
||||
<<: *env-release-build
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-chromedriver-build
|
||||
|
||||
osx-release:
|
||||
<<: *machine-mac-large
|
||||
environment:
|
||||
@@ -1971,9 +1913,9 @@ jobs:
|
||||
environment:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
- electron-publish:
|
||||
attach: false
|
||||
@@ -1984,8 +1926,8 @@ jobs:
|
||||
environment:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
- electron-publish:
|
||||
attach: true
|
||||
@@ -2036,9 +1978,9 @@ jobs:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-mas
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *env-ninja-status
|
||||
steps:
|
||||
- electron-publish:
|
||||
attach: false
|
||||
@@ -2050,7 +1992,6 @@ jobs:
|
||||
<<: *env-mac-large-release
|
||||
<<: *env-mas
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
steps:
|
||||
- electron-publish:
|
||||
@@ -2348,9 +2289,11 @@ workflows:
|
||||
- osx-publish-skip-checkout:
|
||||
requires:
|
||||
- mac-checkout
|
||||
context: release-env
|
||||
- mas-publish-skip-checkout:
|
||||
requires:
|
||||
- mac-checkout
|
||||
context: release-env
|
||||
|
||||
lint:
|
||||
when: << pipeline.parameters.run-lint >>
|
||||
|
||||
@@ -4,4 +4,3 @@
|
||||
APPVEYOR_CLOUD_TOKEN=
|
||||
CIRCLE_TOKEN=
|
||||
ELECTRON_GITHUB_TOKEN=
|
||||
VSTS_TOKEN=
|
||||
@@ -31,7 +31,8 @@
|
||||
"BUILDFLAG": "readonly",
|
||||
"ENABLE_DESKTOP_CAPTURER": "readonly",
|
||||
"ENABLE_REMOTE_MODULE": "readonly",
|
||||
"ENABLE_VIEWS_API": "readonly"
|
||||
"ENABLE_VIEWS_API": "readonly",
|
||||
"BigInt": "readonly"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
|
||||
10
.gitattributes
vendored
10
.gitattributes
vendored
@@ -2,3 +2,13 @@
|
||||
# files to be checked out with LF endings even if core.autocrlf is true.
|
||||
*.patch text eol=lf
|
||||
patches/**/.patches merge=union
|
||||
|
||||
# Source code and markdown files should always use LF as line ending.
|
||||
*.cc text eol=lf
|
||||
*.mm text eol=lf
|
||||
*.h text eol=lf
|
||||
*.js text eol=lf
|
||||
*.ts text eol=lf
|
||||
*.py text eol=lf
|
||||
*.ps1 text eol=lf
|
||||
*.md text eol=lf
|
||||
|
||||
71
BUILD.gn
71
BUILD.gn
@@ -322,10 +322,10 @@ source_set("electron_lib") {
|
||||
"shell/common/api:mojo",
|
||||
"//base:base_static",
|
||||
"//base/allocator:buildflags",
|
||||
"//chrome/app:command_ids",
|
||||
"//chrome/app/resources:platform_locale_settings",
|
||||
"//chrome/services/printing/public/mojom",
|
||||
"//components/certificate_transparency",
|
||||
"//components/crash/core/app",
|
||||
"//components/language/core/browser",
|
||||
"//components/net_log",
|
||||
"//components/network_hints/browser",
|
||||
@@ -362,6 +362,7 @@ source_set("electron_lib") {
|
||||
"//services/viz/privileged/mojom/compositing",
|
||||
"//skia",
|
||||
"//third_party/blink/public:blink",
|
||||
"//third_party/blink/public:blink_devtools_inspector_resources",
|
||||
"//third_party/boringssl",
|
||||
"//third_party/electron_node:node_lib",
|
||||
"//third_party/inspector_protocol:crdtp",
|
||||
@@ -369,6 +370,7 @@ source_set("electron_lib") {
|
||||
"//third_party/libyuv",
|
||||
"//third_party/webrtc_overrides:webrtc_component",
|
||||
"//third_party/widevine/cdm:headers",
|
||||
"//third_party/zlib/google:zip",
|
||||
"//ui/base/idle",
|
||||
"//ui/events:dom_keycode_converter",
|
||||
"//ui/gl",
|
||||
@@ -432,6 +434,9 @@ source_set("electron_lib") {
|
||||
"*\bviews/*",
|
||||
]
|
||||
}
|
||||
if (!is_mas_build) {
|
||||
deps += [ "//components/crash/core/app" ]
|
||||
}
|
||||
|
||||
set_sources_assignment_filter(
|
||||
sources_assignment_filter + extra_source_filters)
|
||||
@@ -457,10 +462,13 @@ source_set("electron_lib") {
|
||||
deps += [
|
||||
"//components/remote_cocoa/app_shim",
|
||||
"//content/common:mac_helpers",
|
||||
"//third_party/crashpad/crashpad/client",
|
||||
"//ui/accelerated_widget_mac",
|
||||
]
|
||||
|
||||
if (!is_mas_build) {
|
||||
deps += [ "//third_party/crashpad/crashpad/client" ]
|
||||
}
|
||||
|
||||
libs = [
|
||||
"AVFoundation.framework",
|
||||
"Carbon.framework",
|
||||
@@ -481,6 +489,12 @@ source_set("electron_lib") {
|
||||
sources += [ "shell/browser/api/electron_api_app_mas.mm" ]
|
||||
sources -= [ "shell/browser/auto_updater_mac.mm" ]
|
||||
defines += [ "MAS_BUILD" ]
|
||||
sources -= [
|
||||
"shell/app/electron_crash_reporter_client.cc",
|
||||
"shell/app/electron_crash_reporter_client.h",
|
||||
"shell/common/crash_keys.cc",
|
||||
"shell/common/crash_keys.h",
|
||||
]
|
||||
} else {
|
||||
libs += [
|
||||
"Squirrel.framework",
|
||||
@@ -523,6 +537,16 @@ source_set("electron_lib") {
|
||||
|
||||
sources += filenames.lib_sources_nss
|
||||
sources += [
|
||||
"shell/browser/ui/gtk/app_indicator_icon.cc",
|
||||
"shell/browser/ui/gtk/app_indicator_icon.h",
|
||||
"shell/browser/ui/gtk/app_indicator_icon_menu.cc",
|
||||
"shell/browser/ui/gtk/app_indicator_icon_menu.h",
|
||||
"shell/browser/ui/gtk/gtk_status_icon.cc",
|
||||
"shell/browser/ui/gtk/gtk_status_icon.h",
|
||||
"shell/browser/ui/gtk/menu_util.cc",
|
||||
"shell/browser/ui/gtk/menu_util.h",
|
||||
"shell/browser/ui/gtk/status_icon.cc",
|
||||
"shell/browser/ui/gtk/status_icon.h",
|
||||
"shell/browser/ui/gtk_util.cc",
|
||||
"shell/browser/ui/gtk_util.h",
|
||||
]
|
||||
@@ -652,6 +676,14 @@ source_set("electron_lib") {
|
||||
"shell/browser/electron_pdf_web_contents_helper_client.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_win && enable_win_dark_mode_window_ui) {
|
||||
sources += [
|
||||
"shell/browser/win/dark_mode.cc",
|
||||
"shell/browser/win/dark_mode.h",
|
||||
]
|
||||
libs += [ "uxtheme.lib" ]
|
||||
}
|
||||
}
|
||||
|
||||
electron_paks("packed_resources") {
|
||||
@@ -763,8 +795,10 @@ if (is_mac) {
|
||||
framework_contents = [
|
||||
"Resources",
|
||||
"Libraries",
|
||||
"Helpers",
|
||||
]
|
||||
if (!is_mas_build) {
|
||||
framework_contents += [ "Helpers" ]
|
||||
}
|
||||
public_deps = [
|
||||
":electron_framework_libraries",
|
||||
":electron_lib",
|
||||
@@ -995,13 +1029,16 @@ if (is_mac) {
|
||||
|
||||
group("electron_symbols") {
|
||||
deps = [
|
||||
":crashpad_handler_syms",
|
||||
":electron_app_syms",
|
||||
":electron_framework_syms",
|
||||
":swiftshader_egl_syms",
|
||||
":swiftshader_gles_syms",
|
||||
]
|
||||
|
||||
if (!is_mas_build) {
|
||||
deps += [ ":crashpad_handler_syms" ]
|
||||
}
|
||||
|
||||
foreach(helper_params, content_mac_helpers) {
|
||||
_helper_target = helper_params[0]
|
||||
deps += [ ":electron_helper_syms_${_helper_target}" ]
|
||||
@@ -1066,22 +1103,32 @@ if (is_mac) {
|
||||
"//components/crash/core/app:run_as_crashpad_handler",
|
||||
]
|
||||
|
||||
ldflags = []
|
||||
|
||||
libs = [
|
||||
"comctl32.lib",
|
||||
"uiautomationcore.lib",
|
||||
"wtsapi32.lib",
|
||||
]
|
||||
|
||||
configs += [ "//build/config/win:windowed" ]
|
||||
|
||||
ldflags = [
|
||||
# Windows 7 doesn't have these DLLs.
|
||||
# TODO: are there other DLLs we need to list here to be win7
|
||||
# compatible?
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll",
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-string-l1-1-0.dll",
|
||||
configs += [
|
||||
"//build/config/win:windowed",
|
||||
"//build/config/win:delayloads",
|
||||
]
|
||||
|
||||
if (current_cpu == "x86") {
|
||||
# Set the initial stack size to 0.5MiB, instead of the 1.5MiB needed by
|
||||
# Chrome's main thread. This saves significant memory on threads (like
|
||||
# those in the Windows thread pool, and others) whose stack size we can
|
||||
# only control through this setting. Because Chrome's main thread needs
|
||||
# a minimum 1.5 MiB stack, the main thread (in 32-bit builds only) uses
|
||||
# fibers to switch to a 1.5 MiB stack before running any other code.
|
||||
ldflags += [ "/STACK:0x80000" ]
|
||||
} else {
|
||||
# Increase the initial stack size. The default is 1MB, this is 8MB.
|
||||
ldflags += [ "/STACK:0x800000" ]
|
||||
}
|
||||
|
||||
# This is to support renaming of electron.exe. node-gyp has hard-coded
|
||||
# executable names which it will recognise as node. This module definition
|
||||
# file claims that the electron executable is in fact named "node.exe",
|
||||
|
||||
9
DEPS
9
DEPS
@@ -5,14 +5,16 @@ gclient_gn_args = [
|
||||
'checkout_android_native_support',
|
||||
'checkout_libaom',
|
||||
'checkout_nacl',
|
||||
'checkout_pgo_profiles',
|
||||
'checkout_oculus_sdk',
|
||||
'checkout_openxr',
|
||||
'checkout_google_benchmark'
|
||||
'checkout_google_benchmark',
|
||||
'mac_xcode_version',
|
||||
]
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'17da1064b910f4170320ff37e971064916aed1dc',
|
||||
'85.0.4183.121',
|
||||
'node_version':
|
||||
'v12.16.3',
|
||||
'nan_version':
|
||||
@@ -42,6 +44,7 @@ vars = {
|
||||
'checkout_chromium': True,
|
||||
'checkout_node': True,
|
||||
'checkout_nan': True,
|
||||
'checkout_pgo_profiles': True,
|
||||
|
||||
# It's only needed to parse the native tests configurations.
|
||||
'checkout_pyyaml': False,
|
||||
@@ -49,6 +52,8 @@ vars = {
|
||||
# Python "requests" module is used for releases only.
|
||||
'checkout_requests': False,
|
||||
|
||||
'mac_xcode_version': 'default',
|
||||
|
||||
# To allow running hooks without parsing the DEPS tree
|
||||
'process_deps': True,
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
10.0.0-nightly.20200521
|
||||
10.4.7
|
||||
@@ -28,15 +28,12 @@ The preferred method is to install Electron as a development dependency in your
|
||||
app:
|
||||
|
||||
```sh
|
||||
npm install electron --save-dev [--save-exact]
|
||||
npm install electron --save-dev
|
||||
```
|
||||
|
||||
The `--save-exact` flag is recommended for Electron prior to version 2, as it does not follow semantic
|
||||
versioning. As of version 2.0.0, Electron follows semver, so you don't need `--save-exact` flag. For info on how to manage Electron versions in your apps, see
|
||||
[Electron versioning](docs/tutorial/electron-versioning.md).
|
||||
|
||||
For more installation options and troubleshooting tips, see
|
||||
[installation](docs/tutorial/installation.md).
|
||||
[installation](docs/tutorial/installation.md). For info on how to manage Electron versions in your apps, see
|
||||
[Electron versioning](docs/tutorial/electron-versioning.md).
|
||||
|
||||
## Quick start & Electron Fiddle
|
||||
|
||||
|
||||
13
appveyor.yml
13
appveyor.yml
@@ -29,13 +29,14 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electron-16-core
|
||||
image: vs2019bt-16.4.0
|
||||
image: vs2019bt-16.6.2
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\electron\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
notifications:
|
||||
- provider: Webhook
|
||||
url: https://electron-mission-control.herokuapp.com/rest/appveyor-hook
|
||||
@@ -53,7 +54,9 @@ build_script:
|
||||
} else {
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
|
||||
if ($(node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH;$LASTEXITCODE -eq 0)) {
|
||||
$result = node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
|
||||
Write-Output $result
|
||||
if ($result.ExitCode -eq 0) {
|
||||
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
|
||||
}
|
||||
}
|
||||
@@ -133,7 +136,7 @@ build_script:
|
||||
cd build-tools
|
||||
npm install
|
||||
mkdir third_party
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare()"
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
$env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
$env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
cd ..
|
||||
@@ -218,10 +221,10 @@ deploy_script:
|
||||
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 --upload_to_s3
|
||||
& python script\release\uploaders\upload.py --verbose --upload_to_s3
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python script\release\uploaders\upload.py
|
||||
& 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
|
||||
|
||||
@@ -71,7 +71,6 @@ steps:
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_TIMEOUT: 120000
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish Test Results'
|
||||
@@ -88,7 +87,11 @@ steps:
|
||||
|
||||
- powershell: |
|
||||
Get-Process | Where Name –Like "electron*" | Stop-Process
|
||||
Get-Process | Where Name –Like "MicrosoftEdge*" | 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()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
|
||||
@@ -9,7 +10,9 @@ config.output = {
|
||||
filename: path.basename(outPath)
|
||||
}
|
||||
|
||||
webpack(config, (err, stats) => {
|
||||
const { wrapInitWithProfilingTimeout, wrapInitWithTryCatch, ...webpackConfig } = config;
|
||||
|
||||
webpack(webpackConfig, (err, stats) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
@@ -17,6 +20,26 @@ webpack(config, (err, stats) => {
|
||||
console.error(stats.toString('normal'))
|
||||
process.exit(1)
|
||||
} else {
|
||||
let contents = fs.readFileSync(outPath, 'utf8');
|
||||
if (wrapInitWithTryCatch) {
|
||||
contents = `try {
|
||||
${contents}
|
||||
} catch (err) {
|
||||
console.error('Electron ${webpackConfig.output.filename} script failed to run');
|
||||
console.error(err);
|
||||
}`;
|
||||
}
|
||||
if (wrapInitWithProfilingTimeout) {
|
||||
contents = `function ___electron_webpack_init__() {
|
||||
${contents}
|
||||
};
|
||||
if ((globalThis.process || binding.process).argv.includes("--profile-electron-init")) {
|
||||
setTimeout(___electron_webpack_init__, 0);
|
||||
} else {
|
||||
___electron_webpack_init__();
|
||||
}`;
|
||||
}
|
||||
fs.writeFileSync(outPath, contents)
|
||||
process.exit(0)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
|
||||
const electronRoot = path.resolve(__dirname, '../..')
|
||||
|
||||
@@ -21,7 +22,7 @@ class AccessDependenciesPlugin {
|
||||
}
|
||||
|
||||
const defines = {
|
||||
BUILDFLAG: ''
|
||||
BUILDFLAG: onlyPrintingGraph ? '(a => a)' : ''
|
||||
}
|
||||
|
||||
const buildFlagsPrefix = '--buildflags='
|
||||
@@ -34,8 +35,7 @@ if (buildFlagArg) {
|
||||
for (const line of flagFile.split(/(\r\n|\r|\n)/g)) {
|
||||
const flagMatch = line.match(/#define BUILDFLAG_INTERNAL_(.+?)\(\) \(([01])\)/)
|
||||
if (flagMatch) {
|
||||
const flagName = flagMatch[1];
|
||||
const flagValue = flagMatch[2];
|
||||
const [, flagName, flagValue] = flagMatch;
|
||||
defines[flagName] = JSON.stringify(Boolean(parseInt(flagValue, 10)));
|
||||
}
|
||||
}
|
||||
@@ -64,16 +64,13 @@ if (defines['ENABLE_VIEWS_API'] === 'false') {
|
||||
)
|
||||
}
|
||||
|
||||
const alias = {}
|
||||
for (const ignoredModule of ignoredModules) {
|
||||
alias[ignoredModule] = path.resolve(electronRoot, 'lib/common/dummy.js')
|
||||
}
|
||||
|
||||
module.exports = ({
|
||||
alwaysHasNode,
|
||||
loadElectronFromAlternateTarget,
|
||||
targetDeletesNodeGlobals,
|
||||
target
|
||||
target,
|
||||
wrapInitWithProfilingTimeout,
|
||||
wrapInitWithTryCatch
|
||||
}) => {
|
||||
let entry = path.resolve(electronRoot, 'lib', target, 'init.ts')
|
||||
if (!fs.existsSync(entry)) {
|
||||
@@ -82,30 +79,37 @@ module.exports = ({
|
||||
|
||||
return ({
|
||||
mode: 'development',
|
||||
devtool: 'inline-source-map',
|
||||
devtool: false,
|
||||
entry,
|
||||
target: alwaysHasNode ? 'node' : 'web',
|
||||
output: {
|
||||
filename: `${target}.bundle.js`
|
||||
},
|
||||
wrapInitWithProfilingTimeout,
|
||||
wrapInitWithTryCatch,
|
||||
resolve: {
|
||||
alias: {
|
||||
...alias,
|
||||
'@electron/internal': path.resolve(electronRoot, 'lib'),
|
||||
'electron': path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.ts'),
|
||||
// Force timers to resolve to our dependency that doens't use window.postMessage
|
||||
// Force timers to resolve to our dependency that doesn't use window.postMessage
|
||||
'timers': path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
|
||||
},
|
||||
extensions: ['.ts', '.js']
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: (moduleName) => !onlyPrintingGraph && ignoredModules.includes(moduleName),
|
||||
loader: 'null-loader',
|
||||
}, {
|
||||
test: /\.ts$/,
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
configFile: path.resolve(electronRoot, 'tsconfig.electron.json'),
|
||||
transpileOnly: onlyPrintingGraph,
|
||||
ignoreDiagnostics: [6059]
|
||||
ignoreDiagnostics: [
|
||||
// File '{0}' is not under 'rootDir' '{1}'.
|
||||
6059,
|
||||
]
|
||||
}
|
||||
}]
|
||||
},
|
||||
@@ -116,6 +120,17 @@ module.exports = ({
|
||||
// one of our renderer bundles should import it from the 'timers' package
|
||||
setImmediate: false,
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
keep_classnames: true,
|
||||
keep_fnames: true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new AccessDependenciesPlugin(),
|
||||
...(targetDeletesNodeGlobals ? [
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'isolated_renderer',
|
||||
alwaysHasNode: false
|
||||
alwaysHasNode: false,
|
||||
wrapInitWithTryCatch: true
|
||||
})
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'renderer',
|
||||
alwaysHasNode: true,
|
||||
targetDeletesNodeGlobals: true
|
||||
targetDeletesNodeGlobals: true,
|
||||
wrapInitWithProfilingTimeout: true,
|
||||
wrapInitWithTryCatch: true
|
||||
})
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'sandboxed_renderer',
|
||||
alwaysHasNode: false
|
||||
alwaysHasNode: false,
|
||||
wrapInitWithProfilingTimeout: true,
|
||||
wrapInitWithTryCatch: true
|
||||
})
|
||||
|
||||
@@ -2,5 +2,6 @@ module.exports = require('./webpack.config.base')({
|
||||
target: 'worker',
|
||||
loadElectronFromAlternateTarget: 'renderer',
|
||||
alwaysHasNode: true,
|
||||
targetDeletesNodeGlobals: true
|
||||
targetDeletesNodeGlobals: true,
|
||||
wrapInitWithTryCatch: true
|
||||
})
|
||||
|
||||
@@ -16,6 +16,7 @@ template("webpack_build") {
|
||||
inputs = [
|
||||
invoker.config_file,
|
||||
"//electron/build/webpack/webpack.config.base.js",
|
||||
"//electron/build/webpack/run-compiler.js",
|
||||
"//electron/tsconfig.json",
|
||||
"//electron/yarn.lock",
|
||||
"//electron/typings/internal-ambient.d.ts",
|
||||
|
||||
@@ -21,6 +21,7 @@ buildflag_header("buildflags") {
|
||||
"ENABLE_ELECTRON_EXTENSIONS=$enable_electron_extensions",
|
||||
"ENABLE_BUILTIN_SPELLCHECKER=$enable_builtin_spellchecker",
|
||||
"ENABLE_PICTURE_IN_PICTURE=$enable_picture_in_picture",
|
||||
"ENABLE_WIN_DARK_MODE_WINDOW_UI=$enable_win_dark_mode_window_ui",
|
||||
"OVERRIDE_LOCATION_PROVIDER=$enable_fake_location_provider",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -36,4 +36,7 @@ declare_args() {
|
||||
|
||||
# Enable Spellchecker support
|
||||
enable_builtin_spellchecker = true
|
||||
|
||||
# Undocumented Windows dark mode API
|
||||
enable_win_dark_mode_window_ui = false
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ static_library("chrome") {
|
||||
]
|
||||
deps = [
|
||||
"//chrome/browser:resource_prefetch_predictor_proto",
|
||||
"//chrome/services/speech:buildflags",
|
||||
"//components/feature_engagement:buildflags",
|
||||
"//components/optimization_guide/proto:optimization_guide_proto",
|
||||
]
|
||||
@@ -92,6 +93,14 @@ static_library("chrome") {
|
||||
]
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
sources += [
|
||||
"//chrome/browser/win/icon_reader_service.cc",
|
||||
"//chrome/browser/win/icon_reader_service.h",
|
||||
]
|
||||
public_deps += [ "//chrome/services/util_win:lib" ]
|
||||
}
|
||||
|
||||
if (enable_desktop_capturer) {
|
||||
sources += [
|
||||
"//chrome/browser/media/webrtc/desktop_media_list.h",
|
||||
@@ -152,13 +161,6 @@ static_library("chrome") {
|
||||
}
|
||||
}
|
||||
|
||||
if (enable_tts) {
|
||||
sources += [
|
||||
"//chrome/browser/speech/tts_controller_delegate_impl.cc",
|
||||
"//chrome/browser/speech/tts_controller_delegate_impl.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_widevine) {
|
||||
sources += [
|
||||
"//chrome/renderer/media/chrome_key_systems.cc",
|
||||
|
||||
@@ -36,6 +36,7 @@ net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
|
||||
// Linux has only a single persistent slot compared to ChromeOS's separate
|
||||
// public and private slot.
|
||||
// Redirect any slot usage to this persistent slot on Linux.
|
||||
crypto::EnsureNSSInit();
|
||||
g_nss_cert_database = new net::NSSCertDatabase(
|
||||
crypto::ScopedPK11Slot(PK11_GetInternalKeySlot()) /* public slot */,
|
||||
crypto::ScopedPK11Slot(PK11_GetInternalKeySlot()) /* private slot */);
|
||||
|
||||
@@ -68,7 +68,6 @@
|
||||
#include "base/logging.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/metrics/histogram_macros.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/posix/eintr_wrapper.h"
|
||||
@@ -827,10 +826,9 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
||||
to_send.append(current_dir.value());
|
||||
|
||||
const std::vector<std::string>& argv = electron::ElectronCommandLine::argv();
|
||||
for (std::vector<std::string>::const_iterator it = argv.begin();
|
||||
it != argv.end(); ++it) {
|
||||
for (const auto& arg : argv) {
|
||||
to_send.push_back(kTokenDelimiter);
|
||||
to_send.append(*it);
|
||||
to_send.append(arg);
|
||||
}
|
||||
|
||||
// Send the message
|
||||
|
||||
@@ -24,18 +24,18 @@ GlobalMenuBarRegistrarX11* GlobalMenuBarRegistrarX11::GetInstance() {
|
||||
return base::Singleton<GlobalMenuBarRegistrarX11>::get();
|
||||
}
|
||||
|
||||
void GlobalMenuBarRegistrarX11::OnWindowMapped(unsigned long xid) {
|
||||
live_xids_.insert(xid);
|
||||
void GlobalMenuBarRegistrarX11::OnWindowMapped(x11::Window window) {
|
||||
live_windows_.insert(window);
|
||||
|
||||
if (registrar_proxy_)
|
||||
RegisterXID(xid);
|
||||
RegisterXWindow(window);
|
||||
}
|
||||
|
||||
void GlobalMenuBarRegistrarX11::OnWindowUnmapped(unsigned long xid) {
|
||||
void GlobalMenuBarRegistrarX11::OnWindowUnmapped(x11::Window window) {
|
||||
if (registrar_proxy_)
|
||||
UnregisterXID(xid);
|
||||
UnregisterXWindow(window);
|
||||
|
||||
live_xids_.erase(xid);
|
||||
live_windows_.erase(window);
|
||||
}
|
||||
|
||||
GlobalMenuBarRegistrarX11::GlobalMenuBarRegistrarX11()
|
||||
@@ -63,9 +63,9 @@ GlobalMenuBarRegistrarX11::~GlobalMenuBarRegistrarX11() {
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalMenuBarRegistrarX11::RegisterXID(unsigned long xid) {
|
||||
void GlobalMenuBarRegistrarX11::RegisterXWindow(x11::Window window) {
|
||||
DCHECK(registrar_proxy_);
|
||||
std::string path = electron::GlobalMenuBarX11::GetPathForWindow(xid);
|
||||
std::string path = electron::GlobalMenuBarX11::GetPathForWindow(window);
|
||||
|
||||
ANNOTATE_SCOPED_MEMORY_LEAK; // http://crbug.com/314087
|
||||
// TODO(erg): The mozilla implementation goes to a lot of callback trouble
|
||||
@@ -76,13 +76,13 @@ void GlobalMenuBarRegistrarX11::RegisterXID(unsigned long xid) {
|
||||
// I don't see any reason why we should care if "RegisterWindow" completes or
|
||||
// not.
|
||||
g_dbus_proxy_call(registrar_proxy_, "RegisterWindow",
|
||||
g_variant_new("(uo)", xid, path.c_str()),
|
||||
g_variant_new("(uo)", window, path.c_str()),
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void GlobalMenuBarRegistrarX11::UnregisterXID(unsigned long xid) {
|
||||
void GlobalMenuBarRegistrarX11::UnregisterXWindow(x11::Window window) {
|
||||
DCHECK(registrar_proxy_);
|
||||
std::string path = electron::GlobalMenuBarX11::GetPathForWindow(xid);
|
||||
std::string path = electron::GlobalMenuBarX11::GetPathForWindow(window);
|
||||
|
||||
ANNOTATE_SCOPED_MEMORY_LEAK; // http://crbug.com/314087
|
||||
// TODO(erg): The mozilla implementation goes to a lot of callback trouble
|
||||
@@ -93,7 +93,7 @@ void GlobalMenuBarRegistrarX11::UnregisterXID(unsigned long xid) {
|
||||
// I don't see any reason why we should care if "UnregisterWindow" completes
|
||||
// or not.
|
||||
g_dbus_proxy_call(registrar_proxy_, "UnregisterWindow",
|
||||
g_variant_new("(u)", xid), G_DBUS_CALL_FLAGS_NONE, -1,
|
||||
g_variant_new("(u)", window), G_DBUS_CALL_FLAGS_NONE, -1,
|
||||
nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
@@ -120,10 +120,9 @@ void GlobalMenuBarRegistrarX11::OnProxyCreated(GObject* source,
|
||||
|
||||
void GlobalMenuBarRegistrarX11::OnNameOwnerChanged(GObject* /* ignored */,
|
||||
GParamSpec* /* ignored */) {
|
||||
// If the name owner changed, we need to reregister all the live xids with
|
||||
// the system.
|
||||
for (std::set<unsigned long>::const_iterator it = live_xids_.begin();
|
||||
it != live_xids_.end(); ++it) {
|
||||
RegisterXID(*it);
|
||||
// If the name owner changed, we need to reregister all the live x11::Window
|
||||
// with the system.
|
||||
for (const auto& window : live_windows_) {
|
||||
RegisterXWindow(window);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,19 +12,20 @@
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/memory/singleton.h"
|
||||
#include "ui/base/glib/glib_signal.h"
|
||||
#include "ui/gfx/x/xproto.h"
|
||||
|
||||
// Advertises our menu bars to Unity.
|
||||
//
|
||||
// GlobalMenuBarX11 is responsible for managing the DbusmenuServer for each
|
||||
// XID. We need a separate object to own the dbus channel to
|
||||
// x11::Window. We need a separate object to own the dbus channel to
|
||||
// com.canonical.AppMenu.Registrar and to register/unregister the mapping
|
||||
// between a XID and the DbusmenuServer instance we are offering.
|
||||
// between a x11::Window and the DbusmenuServer instance we are offering.
|
||||
class GlobalMenuBarRegistrarX11 {
|
||||
public:
|
||||
static GlobalMenuBarRegistrarX11* GetInstance();
|
||||
|
||||
void OnWindowMapped(unsigned long xid);
|
||||
void OnWindowUnmapped(unsigned long xid);
|
||||
void OnWindowMapped(x11::Window window);
|
||||
void OnWindowUnmapped(x11::Window window);
|
||||
|
||||
private:
|
||||
friend struct base::DefaultSingletonTraits<GlobalMenuBarRegistrarX11>;
|
||||
@@ -33,8 +34,8 @@ class GlobalMenuBarRegistrarX11 {
|
||||
~GlobalMenuBarRegistrarX11();
|
||||
|
||||
// Sends the actual message.
|
||||
void RegisterXID(unsigned long xid);
|
||||
void UnregisterXID(unsigned long xid);
|
||||
void RegisterXWindow(x11::Window window);
|
||||
void UnregisterXWindow(x11::Window window);
|
||||
|
||||
CHROMEG_CALLBACK_1(GlobalMenuBarRegistrarX11,
|
||||
void,
|
||||
@@ -49,9 +50,9 @@ class GlobalMenuBarRegistrarX11 {
|
||||
|
||||
GDBusProxy* registrar_proxy_;
|
||||
|
||||
// Window XIDs which want to be registered, but haven't yet been because
|
||||
// x11::Window which want to be registered, but haven't yet been because
|
||||
// we're waiting for the proxy to become available.
|
||||
std::set<unsigned long> live_xids_;
|
||||
std::set<x11::Window> live_windows_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GlobalMenuBarRegistrarX11);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { app, dialog, BrowserWindow, shell, ipcMain } from 'electron';
|
||||
import * as path from 'path';
|
||||
import * as url from 'url';
|
||||
|
||||
let mainWindow: BrowserWindow | null = null;
|
||||
|
||||
@@ -29,26 +30,25 @@ function isTrustedSender (webContents: Electron.WebContents) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const parsedUrl = new URL(webContents.getURL());
|
||||
const urlPath = process.platform === 'win32'
|
||||
// Strip the prefixed "/" that occurs on windows
|
||||
? path.resolve(parsedUrl.pathname.substr(1))
|
||||
: parsedUrl.pathname;
|
||||
return parsedUrl.protocol === 'file:' && urlPath === indexPath;
|
||||
try {
|
||||
return url.fileURLToPath(webContents.getURL()) === indexPath;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ipcMain.handle('bootstrap', (event) => {
|
||||
return isTrustedSender(event.sender) ? electronPath : null;
|
||||
});
|
||||
|
||||
async function createWindow () {
|
||||
async function createWindow (backgroundColor?: string) {
|
||||
await app.whenReady();
|
||||
|
||||
const options: Electron.BrowserWindowConstructorOptions = {
|
||||
width: 960,
|
||||
height: 620,
|
||||
autoHideMenuBar: true,
|
||||
backgroundColor: '#2f3241',
|
||||
backgroundColor,
|
||||
webPreferences: {
|
||||
preload: path.resolve(__dirname, 'preload.js'),
|
||||
contextIsolation: true,
|
||||
@@ -96,7 +96,7 @@ export const loadURL = async (appUrl: string) => {
|
||||
};
|
||||
|
||||
export const loadFile = async (appPath: string) => {
|
||||
mainWindow = await createWindow();
|
||||
mainWindow = await createWindow(appPath === 'index.html' ? '#2f3241' : undefined);
|
||||
mainWindow.loadFile(appPath);
|
||||
mainWindow.focus();
|
||||
};
|
||||
|
||||
@@ -32,7 +32,8 @@ In most cases, you should do everything in the `ready` event handler.
|
||||
|
||||
Returns:
|
||||
|
||||
* `launchInfo` unknown _macOS_
|
||||
* `event` Event
|
||||
* `launchInfo` Record<string, any> _macOS_
|
||||
|
||||
Emitted once, when Electron has finished initializing. On macOS, `launchInfo`
|
||||
holds the `userInfo` of the `NSUserNotification` that was used to open the
|
||||
@@ -359,7 +360,7 @@ Returns:
|
||||
|
||||
Emitted when the GPU process crashes or is killed.
|
||||
|
||||
### Event: 'renderer-process-crashed'
|
||||
### Event: 'renderer-process-crashed' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -387,7 +388,7 @@ Returns:
|
||||
* `killed` - Process was sent a SIGTERM or otherwise killed externally
|
||||
* `crashed` - Process crashed
|
||||
* `oom` - Process ran out of memory
|
||||
* `launch-failure` - Process never successfully launched
|
||||
* `launch-failed` - Process never successfully launched
|
||||
* `integrity-failure` - Windows code integrity checks failed
|
||||
|
||||
Emitted when the renderer process unexpectedly dissapears. This is normally
|
||||
@@ -1267,7 +1268,7 @@ systems Application folder. Use in combination with `app.moveToApplicationsFolde
|
||||
### `app.moveToApplicationsFolder([options])` _macOS_
|
||||
|
||||
* `options` Object (optional)
|
||||
* `conflictHandler` Function<Boolean> (optional) - A handler for potential conflict in move failure.
|
||||
* `conflictHandler` Function\<Boolean> (optional) - A handler for potential conflict in move failure.
|
||||
* `conflictType` String - The type of move conflict encountered by the handler; can be `exists` or `existsAndRunning`, where `exists` means that an app of the same name is present in the Applications directory and `existsAndRunning` means both that it exists and that it's presently running.
|
||||
|
||||
Returns `Boolean` - Whether the move was successful. Please note that if
|
||||
@@ -1403,7 +1404,7 @@ in your app's initialization to ensure that your overridden value is used.
|
||||
|
||||
A `Boolean` which when `true` disables the overrides that Electron has in place
|
||||
to ensure renderer processes are restarted on every navigation. The current
|
||||
default value for this property is `false`.
|
||||
default value for this property is `true`.
|
||||
|
||||
The intention is for these overrides to become disabled by default and then at
|
||||
some point in the future this property will be removed. This property impacts
|
||||
|
||||
@@ -207,11 +207,15 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `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.
|
||||
* `darkTheme` Boolean (optional) - Forces using dark theme for the window, only works on
|
||||
some GTK desktop environments. Default is [`nativeTheme.shouldUseDarkColors`](native-theme.md).
|
||||
some GTK+3 desktop environments. Default is `false`.
|
||||
* `transparent` Boolean (optional) - Makes the window [transparent](frameless-window.md#transparent-window).
|
||||
Default is `false`. On Windows, does not work unless the window is frameless.
|
||||
* `type` String (optional) - The type of window, default is normal window. See more about
|
||||
this below.
|
||||
* `visualEffectState` String (optional) - Specify how the material appearance should reflect window activity state on macOS. Must be used with the `vibrancy` property. Possible values are:
|
||||
* `followWindow` - The backdrop should automatically appear active when the window is active, and inactive when it is not. This is the default.
|
||||
* `active` - The backdrop should always appear active.
|
||||
* `inactive` - The backdrop should always appear inactive.
|
||||
* `titleBarStyle` String (optional) - The style of window title bar.
|
||||
Default is `default`. Possible values are:
|
||||
* `default` - Results in the standard gray opaque Mac title
|
||||
@@ -271,7 +275,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
the `nodeIntegration` option and the APIs available to the preload script
|
||||
are more limited. Read more about the option [here](sandbox-option.md).
|
||||
* `enableRemoteModule` Boolean (optional) - Whether to enable the [`remote`](remote.md) module.
|
||||
Default is `true`.
|
||||
Default is `false`.
|
||||
* `session` [Session](session.md#class-session) (optional) - Sets the session used by the
|
||||
page. Instead of passing the Session object directly, you can also choose to
|
||||
use the `partition` option instead, which accepts a partition string. When
|
||||
@@ -348,6 +352,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
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.
|
||||
* `worldSafeExecuteJavaScript` Boolean (optional) - If true, values returned from `webFrame.executeJavaScript` will be sanitized to ensure JS values
|
||||
can't unsafely cross between worlds when using `contextIsolation`. The default
|
||||
is `false`. In Electron 12, the default will be changed to `true`. _Deprecated_
|
||||
* `nativeWindowOpen` Boolean (optional) - Whether to use native
|
||||
`window.open()`. Defaults to `false`. Child windows will always have node
|
||||
integration disabled unless `nodeIntegrationInSubFrames` is true. **Note:** This option is currently
|
||||
@@ -387,6 +394,13 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
Default is `true`.
|
||||
* `enableWebSQL` Boolean (optional) - Whether to enable the [WebSQL api](https://www.w3.org/TR/webdatabase/).
|
||||
Default is `true`.
|
||||
* `v8CacheOptions` String (optional) - Enforces the v8 code caching policy
|
||||
used by blink. Accepted values are
|
||||
* `none` - Disables code caching
|
||||
* `code` - Heuristic based code caching
|
||||
* `bypassHeatCheck` - Bypass code caching heuristics but with lazy compilation
|
||||
* `bypassHeatCheckAndEagerCompile` - Same as above except compilation is eager.
|
||||
Default policy is `code`.
|
||||
|
||||
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
|
||||
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
|
||||
@@ -1116,7 +1130,7 @@ Disable or enable the window.
|
||||
|
||||
#### `win.isEnabled()`
|
||||
|
||||
Returns Boolean - whether the window is enabled.
|
||||
Returns `Boolean` - whether the window is enabled.
|
||||
|
||||
#### `win.setSize(width, height[, animate])`
|
||||
|
||||
@@ -1659,9 +1673,12 @@ Sets whether the menu bar should be visible. If the menu bar is auto-hide, users
|
||||
|
||||
Returns `Boolean` - Whether the menu bar is visible.
|
||||
|
||||
#### `win.setVisibleOnAllWorkspaces(visible)`
|
||||
#### `win.setVisibleOnAllWorkspaces(visible[, options])`
|
||||
|
||||
* `visible` Boolean
|
||||
* `options` Object (optional)
|
||||
* `visibleOnFullScreen` Boolean (optional) _macOS_ - Sets whether
|
||||
the window should be visible above fullscreen windows
|
||||
|
||||
Sets whether the window should be visible on all workspaces.
|
||||
|
||||
@@ -1812,6 +1829,13 @@ Replacement API for setBrowserView supporting work with multi browser views.
|
||||
|
||||
* `browserView` [BrowserView](browser-view.md)
|
||||
|
||||
#### `win.setTopBrowserView(browserView)` _Experimental_
|
||||
|
||||
* `browserView` [BrowserView](browser-view.md)
|
||||
|
||||
Raises `browserView` above other `BrowserView`s attached to `win`.
|
||||
Throws an error if `browserView` is not attached to `win`.
|
||||
|
||||
#### `win.getBrowserViews()` _Experimental_
|
||||
|
||||
Returns `BrowserView[]` - an array of all BrowserViews that have been attached
|
||||
|
||||
@@ -36,6 +36,10 @@ for integrated authentication. Without `*` prefix the URL has to match exactly.
|
||||
A comma-separated list of servers for which delegation of user credentials is required.
|
||||
Without `*` prefix the URL has to match exactly.
|
||||
|
||||
### --disable-ntlm-v2
|
||||
|
||||
Disables NTLM v2 for posix platforms, no effect elsewhere.
|
||||
|
||||
### --disable-http-cache
|
||||
|
||||
Disables the disk cache for HTTP requests.
|
||||
@@ -194,6 +198,14 @@ logging level for all code in the source files under a `foo/bar` directory.
|
||||
|
||||
This switch only works when `--enable-logging` is also passed.
|
||||
|
||||
### --force_high_performance_gpu
|
||||
|
||||
Force using discrete GPU when there are multiple GPUs available.
|
||||
|
||||
### --force_low_power_gpu
|
||||
|
||||
Force using integrated GPU when there are multiple GPUs available.
|
||||
|
||||
## Node.js Flags
|
||||
|
||||
Electron supports some of the [CLI flags][node-cli] supported by Node.js.
|
||||
|
||||
@@ -156,10 +156,16 @@ parameters in a renderer process will not result in those parameters being sent
|
||||
with crashes that occur in other renderer processes or in the main process.
|
||||
|
||||
**Note:** Parameters have limits on the length of the keys and values. Key
|
||||
names must be no longer than 39 bytes, and values must be no longer than 127
|
||||
names must be no longer than 39 bytes, and values must be no longer than 20320
|
||||
bytes. Keys with names longer than the maximum will be silently ignored. Key
|
||||
values longer than the maximum length will be truncated.
|
||||
|
||||
**Note:** On linux values that are longer than 127 bytes will be chunked into
|
||||
multiple keys, each 127 bytes in length. E.g. `addExtraParameter('foo', 'a'.repeat(130))`
|
||||
will result in two chunked keys `foo__1` and `foo__2`, the first will contain
|
||||
the first 127 bytes and the second will contain the remaining 3 bytes. On
|
||||
your crash reporting backend you should stitch together keys in this format.
|
||||
|
||||
### `crashReporter.removeExtraParameter(key)`
|
||||
|
||||
* `key` String - Parameter key, must be no longer than 39 bytes.
|
||||
|
||||
@@ -52,6 +52,8 @@ Returns:
|
||||
* `method` String - Method name.
|
||||
* `params` any - Event parameters defined by the 'parameters'
|
||||
attribute in the remote debugging protocol.
|
||||
* `sessionId` String - Unique identifier of attached debugging session,
|
||||
will match the value sent from `debugger.sendCommand`.
|
||||
|
||||
Emitted whenever the debugging target issues an instrumentation event.
|
||||
|
||||
@@ -74,11 +76,16 @@ Returns `Boolean` - Whether a debugger is attached to the `webContents`.
|
||||
|
||||
Detaches the debugger from the `webContents`.
|
||||
|
||||
#### `debugger.sendCommand(method[, commandParams])`
|
||||
#### `debugger.sendCommand(method[, commandParams, sessionId])`
|
||||
|
||||
* `method` String - Method name, should be one of the methods defined by the
|
||||
[remote debugging protocol][rdp].
|
||||
* `commandParams` any (optional) - JSON object with request parameters.
|
||||
* `sessionId` String (optional) - send command to the target with associated
|
||||
debugging session id. The initial value can be obtained by sending
|
||||
[Target.attachToTarget][attachToTarget] message.
|
||||
|
||||
[attachToTarget]: https://chromedevtools.github.io/devtools-protocol/tot/Target/#method-attachToTarget
|
||||
|
||||
Returns `Promise<any>` - A promise that resolves with the response defined by
|
||||
the 'returns' attribute of the command description in the remote debugging protocol
|
||||
|
||||
@@ -102,3 +102,21 @@ The following methods of `chrome.tabs` are supported:
|
||||
> **Note:** In Chrome, passing `-1` as a tab ID signifies the "currently active
|
||||
> tab". Since Electron has no such concept, passing `-1` as a tab ID is not
|
||||
> supported and will raise an error.
|
||||
|
||||
### `chrome.management`
|
||||
|
||||
The following methods of `chrome.management` are supported:
|
||||
|
||||
- `chrome.management.getAll`
|
||||
- `chrome.management.get`
|
||||
- `chrome.management.getSelf`
|
||||
- `chrome.management.getPermissionWarningsById`
|
||||
- `chrome.management.getPermissionWarningsByManifest`
|
||||
- `chrome.management.onEnabled`
|
||||
- `chrome.management.onDisabled`
|
||||
|
||||
### `chrome.webRequest`
|
||||
|
||||
All features of this API are supported.
|
||||
|
||||
> **NOTE:** Electron's [`webRequest`](web-request.md) module takes precedence over `chrome.webRequest` if there are conflicting handlers.
|
||||
|
||||
@@ -9,7 +9,7 @@ with the operating system so that you can customize the operations for various
|
||||
shortcuts.
|
||||
|
||||
**Note:** The shortcut is global; it will work even if the app does
|
||||
not have the keyboard focus. You should not use this module until the `ready`
|
||||
not have the keyboard focus. This module cannot be used before the `ready`
|
||||
event of the app module is emitted.
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -91,7 +91,7 @@ Removes listeners of the specified `channel`.
|
||||
### `ipcMain.handle(channel, listener)`
|
||||
|
||||
* `channel` String
|
||||
* `listener` Function<Promise<void> | any>
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `event` IpcMainInvokeEvent
|
||||
* `...args` any[]
|
||||
|
||||
@@ -123,7 +123,7 @@ WebContents is the source of the invoke request.
|
||||
### `ipcMain.handleOnce(channel, listener)`
|
||||
|
||||
* `channel` String
|
||||
* `listener` Function<Promise<void> | any>
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `event` IpcMainInvokeEvent
|
||||
* `...args` any[]
|
||||
|
||||
|
||||
@@ -61,9 +61,13 @@ Algorithm][SCA], just like [`window.postMessage`][], so prototype chains will no
|
||||
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
> **NOTE**: Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects is deprecated, and will begin throwing an exception
|
||||
> starting with Electron 9.
|
||||
> **NOTE:** Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
>
|
||||
> Since the main process does not have support for DOM objects such as
|
||||
> `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over
|
||||
> Electron's IPC to the main process, as the main process would have no way to decode
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
The main process handles it by listening for `channel` with the
|
||||
[`ipcMain`](ipc-main.md) module.
|
||||
@@ -85,9 +89,13 @@ Algorithm][SCA], just like [`window.postMessage`][], so prototype chains will no
|
||||
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
> **NOTE**: Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects is deprecated, and will begin throwing an exception
|
||||
> starting with Electron 9.
|
||||
> **NOTE:** Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
>
|
||||
> Since the main process does not have support for DOM objects such as
|
||||
> `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over
|
||||
> Electron's IPC to the main process, as the main process would have no way to decode
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
The main process should listen for `channel` with
|
||||
[`ipcMain.handle()`](ipc-main.md#ipcmainhandlechannel-listener).
|
||||
@@ -123,9 +131,13 @@ Algorithm][SCA], just like [`window.postMessage`][], so prototype chains will no
|
||||
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
> **NOTE**: Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects is deprecated, and will begin throwing an exception
|
||||
> starting with Electron 9.
|
||||
> **NOTE:** Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
>
|
||||
> Since the main process does not have support for DOM objects such as
|
||||
> `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over
|
||||
> Electron's IPC to the main process, as the main process would have no way to decode
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
The main process handles it by listening for `channel` with [`ipcMain`](ipc-main.md) module,
|
||||
and replies by setting `event.returnValue`.
|
||||
|
||||
@@ -12,7 +12,7 @@ See [`Menu`](menu.md) for examples.
|
||||
* `click` Function (optional) - Will be called with
|
||||
`click(menuItem, browserWindow, event)` when the menu item is clicked.
|
||||
* `menuItem` MenuItem
|
||||
* `browserWindow` [BrowserWindow](browser-window.md)
|
||||
* `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`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `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).
|
||||
@@ -69,6 +69,7 @@ a `type`.
|
||||
The `role` property can have following values:
|
||||
|
||||
* `undo`
|
||||
* `about` - Trigger a native about panel (custom message box on Window, which does not provide its own).
|
||||
* `redo`
|
||||
* `cut`
|
||||
* `copy`
|
||||
@@ -94,7 +95,6 @@ The `role` property can have following values:
|
||||
The following additional roles are available on _macOS_:
|
||||
|
||||
* `appMenu` - Whole default "App" menu (About, Services, etc.)
|
||||
* `about` - Map to the `orderFrontStandardAboutPanel` action.
|
||||
* `hide` - Map to the `hide` action.
|
||||
* `hideOthers` - Map to the `hideOtherApplications` action.
|
||||
* `unhide` - Map to the `unhideAllApplications` action.
|
||||
|
||||
@@ -22,8 +22,10 @@ Sets `menu` as the application menu on macOS. On Windows and Linux, the
|
||||
Also on Windows and Linux, you can use a `&` in the top-level item name to
|
||||
indicate which letter should get a generated accelerator. For example, using
|
||||
`&File` for the file menu would result in a generated `Alt-F` accelerator that
|
||||
opens the associated menu. The indicated character in the button label gets an
|
||||
underline. The `&` character is not displayed on the button label.
|
||||
opens the associated menu. The indicated character in the button label then gets an
|
||||
underline, and the `&` character is not displayed on the button label.
|
||||
|
||||
In order to escape the `&` character in an item name, add a proceeding `&`. For example, `&&File` would result in `&File` displayed on the button label.
|
||||
|
||||
Passing `null` will suppress the default menu. On Windows and Linux,
|
||||
this has the additional effect of removing the menu bar from the window.
|
||||
|
||||
@@ -119,6 +119,13 @@ Returns `NativeImage`
|
||||
|
||||
Creates an empty `NativeImage` instance.
|
||||
|
||||
### `nativeImage.createThumbnailFromPath(path, maxSize)` _macOS_ _Windows_
|
||||
|
||||
* `path` String - path to a file that we intend to construct a thumbnail out of.
|
||||
* `maxSize` [Size](structures/size.md) - the maximum width and height (positive numbers) the thumbnail returned can be. The Windows implementation will ignore `maxSize.height` and scale the height according to `maxSize.width`.
|
||||
|
||||
Returns `Promise<NativeImage>` - fulfilled with the file's thumbnail preview image, which is a [NativeImage](native-image.md).
|
||||
|
||||
### `nativeImage.createFromPath(path)`
|
||||
|
||||
* `path` String
|
||||
|
||||
@@ -8,19 +8,19 @@ Process: [Main](../glossary.md#main-process)
|
||||
|
||||
The `powerMonitor` module emits the following events:
|
||||
|
||||
### Event: 'suspend'
|
||||
### Event: 'suspend' _macOS_ _Windows_
|
||||
|
||||
Emitted when the system is suspending.
|
||||
|
||||
### Event: 'resume'
|
||||
### Event: 'resume' _macOS_ _Windows_
|
||||
|
||||
Emitted when system is resuming.
|
||||
|
||||
### Event: 'on-ac' _Windows_
|
||||
### Event: 'on-ac' _macOS_ _Windows_
|
||||
|
||||
Emitted when the system changes to AC power.
|
||||
|
||||
### Event: 'on-battery' _Windows_
|
||||
### Event: 'on-battery' _macOS_ _Windows_
|
||||
|
||||
Emitted when system changes to battery power.
|
||||
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
# protocol (NetworkService) (Draft)
|
||||
|
||||
This document describes the new protocol APIs based on the [NetworkService](https://www.chromium.org/servicification).
|
||||
|
||||
We don't currently have an estimate of when we will enable the `NetworkService` by
|
||||
default in Electron, but as Chromium is already removing non-`NetworkService`
|
||||
code, we will probably switch before Electron 10.
|
||||
|
||||
The content of this document should be moved to `protocol.md` after we have
|
||||
enabled the `NetworkService` by default in Electron.
|
||||
|
||||
> Register a custom protocol and intercept existing protocol requests.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
An example of implementing a protocol that has the same effect as the
|
||||
`file://` protocol:
|
||||
|
||||
```javascript
|
||||
const { app, protocol } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
protocol.registerFileProtocol('atom', (request, callback) => {
|
||||
const url = request.url.substr(7)
|
||||
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**Note:** All methods unless specified can only be used after the `ready` event
|
||||
of the `app` module gets emitted.
|
||||
|
||||
## Using `protocol` with a custom `partition` or `session`
|
||||
|
||||
A protocol is registered to a specific Electron [`session`](./session.md)
|
||||
object. If you don't specify a session, then your `protocol` will be applied to
|
||||
the default session that Electron uses. However, if you define a `partition` or
|
||||
`session` on your `browserWindow`'s `webPreferences`, then that window will use
|
||||
a different session and your custom protocol will not work if you just use
|
||||
`electron.protocol.XXX`.
|
||||
|
||||
To have your custom protocol work in combination with a custom session, you need
|
||||
to register it to that session explicitly.
|
||||
|
||||
```javascript
|
||||
const { session, app, protocol } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const partition = 'persist:example'
|
||||
const ses = session.fromPartition(partition)
|
||||
|
||||
ses.protocol.registerFileProtocol('atom', (request, callback) => {
|
||||
const url = request.url.substr(7)
|
||||
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
||||
})
|
||||
|
||||
mainWindow = new BrowserWindow({ webPreferences: { partition } })
|
||||
})
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
The `protocol` module has the following methods:
|
||||
|
||||
### `protocol.registerSchemesAsPrivileged(customSchemes)`
|
||||
|
||||
* `customSchemes` [CustomScheme[]](structures/custom-scheme.md)
|
||||
|
||||
**Note:** This method can only be used before the `ready` event of the `app`
|
||||
module gets emitted and can be called only once.
|
||||
|
||||
Registers the `scheme` as standard, secure, bypasses content security policy for
|
||||
resources, allows registering ServiceWorker and supports fetch API. Specify a
|
||||
privilege with the value of `true` to enable the capability.
|
||||
|
||||
An example of registering a privileged scheme, that bypasses Content Security
|
||||
Policy:
|
||||
|
||||
```javascript
|
||||
const { protocol } = require('electron')
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
{ scheme: 'foo', privileges: { bypassCSP: true } }
|
||||
])
|
||||
```
|
||||
|
||||
A standard scheme adheres to what RFC 3986 calls [generic URI
|
||||
syntax](https://tools.ietf.org/html/rfc3986#section-3). For example `http` and
|
||||
`https` are standard schemes, while `file` is not.
|
||||
|
||||
Registering a scheme as standard allows relative and absolute resources to
|
||||
be resolved correctly when served. Otherwise the scheme will behave like the
|
||||
`file` protocol, but without the ability to resolve relative URLs.
|
||||
|
||||
For example when you load following page with custom protocol without
|
||||
registering it as standard scheme, the image will not be loaded because
|
||||
non-standard schemes can not recognize relative URLs:
|
||||
|
||||
```html
|
||||
<body>
|
||||
<img src='test.png'>
|
||||
</body>
|
||||
```
|
||||
|
||||
Registering a scheme as standard will allow access to files through the
|
||||
[FileSystem API][file-system-api]. Otherwise the renderer will throw a security
|
||||
error for the scheme.
|
||||
|
||||
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB,
|
||||
cookies) are disabled for non standard schemes. So in general if you want to
|
||||
register a custom protocol to replace the `http` protocol, you have to register
|
||||
it as a standard scheme.
|
||||
|
||||
### `protocol.registerFileProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Registers a protocol of `scheme` that will send a file as the response. The
|
||||
`handler` will be called with `request` and `callback` where `request` is
|
||||
an incoming request for the `scheme`.
|
||||
|
||||
To handle the `request`, the `callback` should be called with either the file's
|
||||
path or an object that has a `path` property, e.g. `callback(filePath)` or
|
||||
`callback({ path: filePath })`. The `filePath` must be an absolute path.
|
||||
|
||||
By default the `scheme` is treated like `http:`, which is parsed differently
|
||||
from protocols that follow the "generic URI syntax" like `file:`.
|
||||
|
||||
### `protocol.registerBufferProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Registers a protocol of `scheme` that will send a `Buffer` as a response.
|
||||
|
||||
The usage is the same with `registerFileProtocol`, except that the `callback`
|
||||
should be called with either a `Buffer` object or an object that has the `data`
|
||||
property.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
protocol.registerBufferProtocol('atom', (request, callback) => {
|
||||
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
|
||||
})
|
||||
```
|
||||
|
||||
### `protocol.registerStringProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Registers a protocol of `scheme` that will send a `String` as a response.
|
||||
|
||||
The usage is the same with `registerFileProtocol`, except that the `callback`
|
||||
should be called with either a `String` or an object that has the `data`
|
||||
property.
|
||||
|
||||
### `protocol.registerHttpProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `response` ProtocolResponse
|
||||
|
||||
Registers a protocol of `scheme` that will send an HTTP request as a response.
|
||||
|
||||
The usage is the same with `registerFileProtocol`, except that the `callback`
|
||||
should be called with an object that has the `url` property.
|
||||
|
||||
### `protocol.registerStreamProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Registers a protocol of `scheme` that will send a stream as a response.
|
||||
|
||||
The usage is the same with `registerFileProtocol`, except that the
|
||||
`callback` should be called with either a [`ReadableStream`](https://nodejs.org/api/stream.html#stream_class_stream_readable) object or an object that
|
||||
has the `data` property.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
const { protocol } = require('electron')
|
||||
const { PassThrough } = require('stream')
|
||||
|
||||
function createStream (text) {
|
||||
const rv = new PassThrough() // PassThrough is also a Readable stream
|
||||
rv.push(text)
|
||||
rv.push(null)
|
||||
return rv
|
||||
}
|
||||
|
||||
protocol.registerStreamProtocol('atom', (request, callback) => {
|
||||
callback({
|
||||
statusCode: 200,
|
||||
headers: {
|
||||
'content-type': 'text/html'
|
||||
},
|
||||
data: createStream('<h5>Response</h5>')
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
It is possible to pass any object that implements the readable stream API (emits
|
||||
`data`/`end`/`error` events). For example, here's how a file could be returned:
|
||||
|
||||
```javascript
|
||||
protocol.registerStreamProtocol('atom', (request, callback) => {
|
||||
callback(fs.createReadStream('index.html'))
|
||||
})
|
||||
```
|
||||
|
||||
### `protocol.unregisterProtocol(scheme)`
|
||||
|
||||
* `scheme` String
|
||||
|
||||
Unregisters the custom protocol of `scheme`.
|
||||
|
||||
### `protocol.isProtocolRegistered(scheme)`
|
||||
|
||||
* `scheme` String
|
||||
|
||||
Returns `Boolean` - Whether `scheme` is already registered.
|
||||
|
||||
### `protocol.interceptFileProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||
which sends a file as a response.
|
||||
|
||||
### `protocol.interceptStringProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||
which sends a `String` as a response.
|
||||
|
||||
### `protocol.interceptBufferProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||
which sends a `Buffer` as a response.
|
||||
|
||||
### `protocol.interceptHttpProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `response` ProtocolResponse
|
||||
|
||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||
which sends a new HTTP request as a response.
|
||||
|
||||
### `protocol.interceptStreamProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Same as `protocol.registerStreamProtocol`, except that it replaces an existing
|
||||
protocol handler.
|
||||
|
||||
### `protocol.uninterceptProtocol(scheme)`
|
||||
|
||||
* `scheme` String
|
||||
|
||||
Remove the interceptor installed for `scheme` and restore its original handler.
|
||||
|
||||
### `protocol.isProtocolIntercepted(scheme)`
|
||||
|
||||
* `scheme` String
|
||||
|
||||
Returns `Boolean` - Whether `scheme` is already intercepted.
|
||||
|
||||
[file-system-api]: https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem
|
||||
@@ -15,8 +15,6 @@ app.whenReady().then(() => {
|
||||
protocol.registerFileProtocol('atom', (request, callback) => {
|
||||
const url = request.url.substr(7)
|
||||
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
||||
}, (error) => {
|
||||
if (error) console.error('Failed to register protocol')
|
||||
})
|
||||
})
|
||||
```
|
||||
@@ -26,9 +24,15 @@ of the `app` module gets emitted.
|
||||
|
||||
## Using `protocol` with a custom `partition` or `session`
|
||||
|
||||
A protocol is registered to a specific Electron [`session`](./session.md) object. If you don't specify a session, then your `protocol` will be applied to the default session that Electron uses. However, if you define a `partition` or `session` on your `browserWindow`'s `webPreferences`, then that window will use a different session and your custom protocol will not work if you just use `electron.protocol.XXX`.
|
||||
A protocol is registered to a specific Electron [`session`](./session.md)
|
||||
object. If you don't specify a session, then your `protocol` will be applied to
|
||||
the default session that Electron uses. However, if you define a `partition` or
|
||||
`session` on your `browserWindow`'s `webPreferences`, then that window will use
|
||||
a different session and your custom protocol will not work if you just use
|
||||
`electron.protocol.XXX`.
|
||||
|
||||
To have your custom protocol work in combination with a custom session, you need to register it to that session explicitly.
|
||||
To have your custom protocol work in combination with a custom session, you need
|
||||
to register it to that session explicitly.
|
||||
|
||||
```javascript
|
||||
const { session, app, protocol } = require('electron')
|
||||
@@ -41,17 +45,9 @@ app.whenReady().then(() => {
|
||||
ses.protocol.registerFileProtocol('atom', (request, callback) => {
|
||||
const url = request.url.substr(7)
|
||||
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
||||
}, (error) => {
|
||||
if (error) console.error('Failed to register protocol')
|
||||
})
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
partition: partition
|
||||
}
|
||||
})
|
||||
mainWindow = new BrowserWindow({ webPreferences: { partition } })
|
||||
})
|
||||
```
|
||||
|
||||
@@ -63,15 +59,15 @@ The `protocol` module has the following methods:
|
||||
|
||||
* `customSchemes` [CustomScheme[]](structures/custom-scheme.md)
|
||||
|
||||
|
||||
**Note:** This method can only be used before the `ready` event of the `app`
|
||||
module gets emitted and can be called only once.
|
||||
|
||||
Registers the `scheme` as standard, secure, bypasses content security policy for resources,
|
||||
allows registering ServiceWorker and supports fetch API.
|
||||
Registers the `scheme` as standard, secure, bypasses content security policy for
|
||||
resources, allows registering ServiceWorker and supports fetch API. Specify a
|
||||
privilege with the value of `true` to enable the capability.
|
||||
|
||||
Specify a privilege with the value of `true` to enable the capability.
|
||||
An example of registering a privileged scheme, with bypassing Content Security Policy:
|
||||
An example of registering a privileged scheme, that bypasses Content Security
|
||||
Policy:
|
||||
|
||||
```javascript
|
||||
const { protocol } = require('electron')
|
||||
@@ -84,7 +80,7 @@ A standard scheme adheres to what RFC 3986 calls [generic URI
|
||||
syntax](https://tools.ietf.org/html/rfc3986#section-3). For example `http` and
|
||||
`https` are standard schemes, while `file` is not.
|
||||
|
||||
Registering a scheme as standard, will allow relative and absolute resources to
|
||||
Registering a scheme as standard allows relative and absolute resources to
|
||||
be resolved correctly when served. Otherwise the scheme will behave like the
|
||||
`file` protocol, but without the ability to resolve relative URLs.
|
||||
|
||||
@@ -102,168 +98,102 @@ Registering a scheme as standard will allow access to files through the
|
||||
[FileSystem API][file-system-api]. Otherwise the renderer will throw a security
|
||||
error for the scheme.
|
||||
|
||||
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB, cookies)
|
||||
are disabled for non standard schemes. So in general if you want to register a
|
||||
custom protocol to replace the `http` protocol, you have to register it as a standard scheme.
|
||||
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB,
|
||||
cookies) are disabled for non standard schemes. So in general if you want to
|
||||
register a custom protocol to replace the `http` protocol, you have to register
|
||||
it as a standard scheme.
|
||||
|
||||
`protocol.registerSchemesAsPrivileged` can be used to replicate the functionality of the previous `protocol.registerStandardSchemes`, `webFrame.registerURLSchemeAs*` and `protocol.registerServiceWorkerSchemes` functions that existed prior to Electron 5.0.0, for example:
|
||||
|
||||
**before (<= v4.x)**
|
||||
```javascript
|
||||
// Main
|
||||
protocol.registerStandardSchemes(['scheme1', 'scheme2'], { secure: true })
|
||||
// Renderer
|
||||
webFrame.registerURLSchemeAsPrivileged('scheme1', { secure: true })
|
||||
webFrame.registerURLSchemeAsPrivileged('scheme2', { secure: true })
|
||||
```
|
||||
|
||||
**after (>= v5.x)**
|
||||
```javascript
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
{ scheme: 'scheme1', privileges: { standard: true, secure: true } },
|
||||
{ scheme: 'scheme2', privileges: { standard: true, secure: true } }
|
||||
])
|
||||
```
|
||||
|
||||
### `protocol.registerFileProtocol(scheme, handler[, completion])`
|
||||
### `protocol.registerFileProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Record<String, String>
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `filePath` String | [FilePathWithHeaders](structures/file-path-with-headers.md) (optional)
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Registers a protocol of `scheme` that will send the file as a response. The
|
||||
`handler` will be called with `handler(request, callback)` when a `request` is
|
||||
going to be created with `scheme`. `completion` will be called with
|
||||
`completion(null)` when `scheme` is successfully registered or
|
||||
`completion(error)` when failed.
|
||||
Returns `Boolean` - Whether the protocol was successfully registered
|
||||
|
||||
Registers a protocol of `scheme` that will send a file as the response. The
|
||||
`handler` will be called with `request` and `callback` where `request` is
|
||||
an incoming request for the `scheme`.
|
||||
|
||||
To handle the `request`, the `callback` should be called with either the file's
|
||||
path or an object that has a `path` property, e.g. `callback(filePath)` or
|
||||
`callback({ path: filePath })`. The object may also have a `headers` property
|
||||
which gives a map of headers to values for the response headers, e.g.
|
||||
`callback({ path: filePath, headers: {"Content-Security-Policy": "default-src 'none'"]})`.
|
||||
|
||||
When `callback` is called with nothing, a number, or an object that has an
|
||||
`error` property, the `request` will fail with the `error` number you
|
||||
specified. For the available error numbers you can use, please see the
|
||||
[net error list][net-error].
|
||||
`callback({ path: filePath })`. The `filePath` must be an absolute path.
|
||||
|
||||
By default the `scheme` is treated like `http:`, which is parsed differently
|
||||
than protocols that follow the "generic URI syntax" like `file:`.
|
||||
from protocols that follow the "generic URI syntax" like `file:`.
|
||||
|
||||
### `protocol.registerBufferProtocol(scheme, handler[, completion])`
|
||||
### `protocol.registerBufferProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Record<String, String>
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `buffer` (Buffer | [MimeTypedBuffer](structures/mime-typed-buffer.md)) (optional)
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Returns `Boolean` - Whether the protocol was successfully registered
|
||||
|
||||
Registers a protocol of `scheme` that will send a `Buffer` as a response.
|
||||
|
||||
The usage is the same with `registerFileProtocol`, except that the `callback`
|
||||
should be called with either a `Buffer` object or an object that has the `data`,
|
||||
`mimeType`, and `charset` properties.
|
||||
should be called with either a `Buffer` object or an object that has the `data`
|
||||
property.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
const { protocol } = require('electron')
|
||||
|
||||
protocol.registerBufferProtocol('atom', (request, callback) => {
|
||||
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
|
||||
}, (error) => {
|
||||
if (error) console.error('Failed to register protocol')
|
||||
})
|
||||
```
|
||||
|
||||
### `protocol.registerStringProtocol(scheme, handler[, completion])`
|
||||
### `protocol.registerStringProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Record<String, String>
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `data` (String | [StringProtocolResponse](structures/string-protocol-response.md)) (optional)
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Returns `Boolean` - Whether the protocol was successfully registered
|
||||
|
||||
Registers a protocol of `scheme` that will send a `String` as a response.
|
||||
|
||||
The usage is the same with `registerFileProtocol`, except that the `callback`
|
||||
should be called with either a `String` or an object that has the `data`,
|
||||
`mimeType`, and `charset` properties.
|
||||
should be called with either a `String` or an object that has the `data`
|
||||
property.
|
||||
|
||||
### `protocol.registerHttpProtocol(scheme, handler[, completion])`
|
||||
### `protocol.registerHttpProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Record<String, String>
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `redirectRequest` Object
|
||||
* `url` String
|
||||
* `method` String (optional)
|
||||
* `session` Session | null (optional)
|
||||
* `uploadData` [ProtocolResponseUploadData](structures/protocol-response-upload-data.md) (optional)
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
* `response` ProtocolResponse
|
||||
|
||||
Returns `Boolean` - Whether the protocol was successfully registered
|
||||
|
||||
Registers a protocol of `scheme` that will send an HTTP request as a response.
|
||||
|
||||
The usage is the same with `registerFileProtocol`, except that the `callback`
|
||||
should be called with a `redirectRequest` object that has the `url`, `method`,
|
||||
`referrer`, `uploadData` and `session` properties.
|
||||
should be called with an object that has the `url` property.
|
||||
|
||||
By default the HTTP request will reuse the current session. If you want the
|
||||
request to have a different session you should set `session` to `null`.
|
||||
|
||||
For POST requests the `uploadData` object must be provided.
|
||||
|
||||
### `protocol.registerStreamProtocol(scheme, handler[, completion])`
|
||||
### `protocol.registerStreamProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Record<String, String>
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `stream` (ReadableStream | [StreamProtocolResponse](structures/stream-protocol-response.md)) (optional)
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Registers a protocol of `scheme` that will send a `Readable` as a response.
|
||||
Returns `Boolean` - Whether the protocol was successfully registered
|
||||
|
||||
The usage is similar to the other `register{Any}Protocol`, except that the
|
||||
`callback` should be called with either a `Readable` object or an object that
|
||||
has the `data`, `statusCode`, and `headers` properties.
|
||||
Registers a protocol of `scheme` that will send a stream as a response.
|
||||
|
||||
The usage is the same with `registerFileProtocol`, except that the
|
||||
`callback` should be called with either a [`ReadableStream`](https://nodejs.org/api/stream.html#stream_class_stream_readable) object or an object that
|
||||
has the `data` property.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -286,8 +216,6 @@ protocol.registerStreamProtocol('atom', (request, callback) => {
|
||||
},
|
||||
data: createStream('<h5>Response</h5>')
|
||||
})
|
||||
}, (error) => {
|
||||
if (error) console.error('Failed to register protocol')
|
||||
})
|
||||
```
|
||||
|
||||
@@ -295,132 +223,102 @@ It is possible to pass any object that implements the readable stream API (emits
|
||||
`data`/`end`/`error` events). For example, here's how a file could be returned:
|
||||
|
||||
```javascript
|
||||
const { protocol } = require('electron')
|
||||
const fs = require('fs')
|
||||
|
||||
protocol.registerStreamProtocol('atom', (request, callback) => {
|
||||
callback(fs.createReadStream('index.html'))
|
||||
}, (error) => {
|
||||
if (error) console.error('Failed to register protocol')
|
||||
})
|
||||
```
|
||||
|
||||
### `protocol.unregisterProtocol(scheme[, completion])`
|
||||
### `protocol.unregisterProtocol(scheme)`
|
||||
|
||||
* `scheme` String
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
|
||||
Returns `Boolean` - Whether the protocol was successfully unregistered
|
||||
|
||||
Unregisters the custom protocol of `scheme`.
|
||||
|
||||
### `protocol.isProtocolHandled(scheme)`
|
||||
### `protocol.isProtocolRegistered(scheme)`
|
||||
|
||||
* `scheme` String
|
||||
|
||||
Returns `Promise<Boolean>` - fulfilled with a boolean that indicates whether there is
|
||||
already a handler for `scheme`.
|
||||
Returns `Boolean` - Whether `scheme` is already registered.
|
||||
|
||||
### `protocol.interceptFileProtocol(scheme, handler[, completion])`
|
||||
### `protocol.interceptFileProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Record<String, String>
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `filePath` String
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Returns `Boolean` - Whether the protocol was successfully intercepted
|
||||
|
||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||
which sends a file as a response.
|
||||
|
||||
### `protocol.interceptStringProtocol(scheme, handler[, completion])`
|
||||
### `protocol.interceptStringProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Record<String, String>
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `data` (String | [StringProtocolResponse](structures/string-protocol-response.md)) (optional)
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Returns `Boolean` - Whether the protocol was successfully intercepted
|
||||
|
||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||
which sends a `String` as a response.
|
||||
|
||||
### `protocol.interceptBufferProtocol(scheme, handler[, completion])`
|
||||
### `protocol.interceptBufferProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Record<String, String>
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `buffer` Buffer (optional)
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Returns `Boolean` - Whether the protocol was successfully intercepted
|
||||
|
||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||
which sends a `Buffer` as a response.
|
||||
|
||||
### `protocol.interceptHttpProtocol(scheme, handler[, completion])`
|
||||
### `protocol.interceptHttpProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Record<String, String>
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `redirectRequest` Object
|
||||
* `url` String
|
||||
* `method` String (optional)
|
||||
* `session` Session | null (optional)
|
||||
* `uploadData` [ProtocolResponseUploadData](structures/protocol-response-upload-data.md) (optional)
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
* `response` [ProtocolResponse](structures/protocol-response.md)
|
||||
|
||||
Returns `Boolean` - Whether the protocol was successfully intercepted
|
||||
|
||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||
which sends a new HTTP request as a response.
|
||||
|
||||
### `protocol.interceptStreamProtocol(scheme, handler[, completion])`
|
||||
### `protocol.interceptStreamProtocol(scheme, handler)`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Record<String, String>
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
* `request` ProtocolRequest
|
||||
* `callback` Function
|
||||
* `stream` (ReadableStream | [StreamProtocolResponse](structures/stream-protocol-response.md)) (optional)
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
|
||||
|
||||
Returns `Boolean` - Whether the protocol was successfully intercepted
|
||||
|
||||
Same as `protocol.registerStreamProtocol`, except that it replaces an existing
|
||||
protocol handler.
|
||||
|
||||
### `protocol.uninterceptProtocol(scheme[, completion])`
|
||||
### `protocol.uninterceptProtocol(scheme)`
|
||||
|
||||
* `scheme` String
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
|
||||
Returns `Boolean` - Whether the protocol was successfully unintercepted
|
||||
|
||||
Remove the interceptor installed for `scheme` and restore its original handler.
|
||||
|
||||
[net-error]: https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h
|
||||
### `protocol.isProtocolIntercepted(scheme)`
|
||||
|
||||
* `scheme` String
|
||||
|
||||
Returns `Boolean` - Whether `scheme` is already intercepted.
|
||||
|
||||
[file-system-api]: https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem
|
||||
|
||||
@@ -376,7 +376,7 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
|
||||
|
||||
#### `ses.setPermissionCheckHandler(handler)`
|
||||
|
||||
* `handler` Function<Boolean> | null
|
||||
* `handler` Function\<Boolean> | null
|
||||
* `webContents` [WebContents](web-contents.md) - WebContents checking the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin.
|
||||
* `permission` String - Enum of 'media'.
|
||||
* `requestingOrigin` String - The origin URL of the permission check
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# IpcMainEvent Object extends `Event`
|
||||
|
||||
* `processId` Integer - The internal ID of the renderer process that sent this message
|
||||
* `frameId` Integer - The ID of the renderer frame that sent this message
|
||||
* `returnValue` any - Set this to the value to be returned in a synchronous message
|
||||
* `sender` WebContents - Returns the `webContents` that sent the message
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# IpcMainInvokeEvent Object extends `Event`
|
||||
|
||||
* `processId` Integer - The internal ID of the renderer process that sent this message
|
||||
* `frameId` Integer - The ID of the renderer frame that sent this message
|
||||
* `sender` WebContents - Returns the `webContents` that sent the message
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
* `contentLengths` Number[] - The total size of the content, in bytes.
|
||||
* `price` Number - The cost of the product in the local currency.
|
||||
* `formattedPrice` String - The locale formatted price of the product.
|
||||
* `currencyCode` String - 3 character code presenting a product's currency based on the ISO 4217 standard.
|
||||
* `isDownloadable` Boolean - A Boolean value that indicates whether the App Store has downloadable content for this product. `true` if at least one file has been associated with the product.
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](upload-data.md) (optional)
|
||||
* `headers` Record<String, String>
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# StreamProtocolResponse Object
|
||||
|
||||
* `statusCode` Number (optional) - The HTTP response code.
|
||||
* `headers` Record<String, String | String[]> (optional) - An object containing the response headers.
|
||||
* `data` ReadableStream | null - A Node.js readable stream representing the response body.
|
||||
@@ -1,5 +0,0 @@
|
||||
# StringProtocolResponse Object
|
||||
|
||||
* `mimeType` String (optional) - MIME type of the response.
|
||||
* `charset` String (optional) - Charset of the response.
|
||||
* `data` String | null - A string representing the response body.
|
||||
@@ -132,6 +132,8 @@ This is necessary for events such as `NSUserDefaultsDidChangeNotification`.
|
||||
* `userInfo` Record<String, unknown>
|
||||
* `object` String
|
||||
|
||||
Returns `Number` - The ID of this subscription
|
||||
|
||||
Same as `subscribeNotification`, but uses `NSWorkspace.sharedWorkspace.notificationCenter`.
|
||||
This is necessary for events such as `NSWorkspaceDidActivateApplicationNotification`.
|
||||
|
||||
@@ -416,7 +418,7 @@ This API itself will not protect your user data; rather, it is a mechanism to al
|
||||
|
||||
Returns `Boolean` - `true` if the current process is a trusted accessibility client and `false` if it is not.
|
||||
|
||||
### `systemPreferences.getMediaAccessStatus(mediaType)` _macOS_
|
||||
### `systemPreferences.getMediaAccessStatus(mediaType)` _Windows_ _macOS_
|
||||
|
||||
* `mediaType` String - Can be `microphone`, `camera` or `screen`.
|
||||
|
||||
@@ -426,6 +428,9 @@ This user consent was not required on macOS 10.13 High Sierra or lower so this m
|
||||
macOS 10.14 Mojave or higher requires consent for `microphone` and `camera` access.
|
||||
macOS 10.15 Catalina or higher requires consent for `screen` access.
|
||||
|
||||
Windows 10 has a global setting controlling `microphone` and `camera` access for all win32 applications.
|
||||
It will always return `granted` for `screen` and for all media types on older versions of Windows.
|
||||
|
||||
### `systemPreferences.askForMediaAccess(mediaType)` _macOS_
|
||||
|
||||
* `mediaType` String - the type of media being requested; can be `microphone`, `camera`.
|
||||
|
||||
@@ -364,7 +364,7 @@ Returns:
|
||||
* `killed` - Process was sent a SIGTERM or otherwise killed externally
|
||||
* `crashed` - Process crashed
|
||||
* `oom` - Process ran out of memory
|
||||
* `launch-failure` - Process never successfully launched
|
||||
* `launch-failed` - Process never successfully launched
|
||||
* `integrity-failure` - Windows code integrity checks failed
|
||||
|
||||
Emitted when the renderer process unexpectedly dissapears. This is normally
|
||||
@@ -402,6 +402,7 @@ Returns:
|
||||
* `key` String - Equivalent to [KeyboardEvent.key][keyboardevent].
|
||||
* `code` String - Equivalent to [KeyboardEvent.code][keyboardevent].
|
||||
* `isAutoRepeat` Boolean - Equivalent to [KeyboardEvent.repeat][keyboardevent].
|
||||
* `isComposing` Boolean - Equivalent to [KeyboardEvent.isComposing][keyboardevent].
|
||||
* `shift` Boolean - Equivalent to [KeyboardEvent.shiftKey][keyboardevent].
|
||||
* `control` Boolean - Equivalent to [KeyboardEvent.controlKey][keyboardevent].
|
||||
* `alt` Boolean - Equivalent to [KeyboardEvent.altKey][keyboardevent].
|
||||
@@ -907,10 +908,10 @@ Returns `String` - The URL of the current web page.
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL('http://github.com')
|
||||
|
||||
let currentURL = win.webContents.getURL()
|
||||
console.log(currentURL)
|
||||
win.loadURL('http://github.com').then(() => {
|
||||
const currentURL = win.webContents.getURL()
|
||||
console.log(currentURL)
|
||||
})
|
||||
```
|
||||
|
||||
#### `contents.getTitle()`
|
||||
@@ -1295,9 +1296,9 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
|
||||
* `pagesPerSheet` Number (optional) - The number of pages to print per page sheet.
|
||||
* `collate` Boolean (optional) - Whether the web page should be collated.
|
||||
* `copies` Number (optional) - The number of copies of the web page to print.
|
||||
* `pageRanges` Record<string, number> (optional) - The page range to print.
|
||||
* `from` Number - the start page.
|
||||
* `to` Number - the end page.
|
||||
* `pageRanges` Object[] (optional) - The page range to print. On macOS, only one range is honored.
|
||||
* `from` Number - Index of the first page to print (0-based).
|
||||
* `to` Number - Index of the last page to print (inclusive) (0-based).
|
||||
* `duplexMode` String (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
|
||||
* `dpi` Record<string, number> (optional)
|
||||
* `horizontal` Number (optional) - The horizontal dpi.
|
||||
@@ -1310,6 +1311,8 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
|
||||
* `success` Boolean - Indicates success of the print call.
|
||||
* `failureReason` String - Error description called back if the print fails.
|
||||
|
||||
When a custom `pageSize` is passed, Chromium attempts to validate platform specific minumum values for `width_microns` and `height_microns`. Width and height must both be minimum 353 microns but may be higher on some operating systems.
|
||||
|
||||
Prints window's web page. When `silent` is set to `true`, Electron will pick
|
||||
the system's default printer if `deviceName` is empty and the default settings for printing.
|
||||
|
||||
@@ -1333,13 +1336,12 @@ win.webContents.print(options, (success, errorType) => {
|
||||
* `landscape` Boolean (optional) - `true` for landscape, `false` for portrait.
|
||||
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
|
||||
default margin, 1 for no margin, and 2 for minimum margin.
|
||||
and `width` in microns.
|
||||
* `scaleFactor` Number (optional) - The scale factor of the web page. Can range from 0 to 100.
|
||||
* `pageRanges` Record<string, number> (optional) - The page range to print.
|
||||
* `from` Number - the first page to print.
|
||||
* `to` Number - the last page to print (inclusive).
|
||||
* `from` Number - Index of the first page to print (0-based).
|
||||
* `to` Number - Index of the last page to print (inclusive) (0-based).
|
||||
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width` in microns.
|
||||
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
|
||||
* `printSelectionOnly` Boolean (optional) - Whether to print selection only.
|
||||
|
||||
@@ -1370,6 +1372,8 @@ An example of `webContents.printToPDF`:
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
|
||||
let win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL('http://github.com')
|
||||
@@ -1377,12 +1381,13 @@ win.loadURL('http://github.com')
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
// Use default printing options
|
||||
win.webContents.printToPDF({}).then(data => {
|
||||
fs.writeFile('/tmp/print.pdf', data, (error) => {
|
||||
const pdfPath = path.join(os.homedir(), 'Desktop', 'temp.pdf')
|
||||
fs.writeFile(pdfPath, data, (error) => {
|
||||
if (error) throw error
|
||||
console.log('Write PDF successfully.')
|
||||
console.log(`Wrote PDF successfully to ${pdfPath}`)
|
||||
})
|
||||
}).catch(error => {
|
||||
console.log(error)
|
||||
console.log(`Failed to write PDF to ${pdfPath}: `, error)
|
||||
})
|
||||
})
|
||||
```
|
||||
@@ -1544,8 +1549,7 @@ included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
> **NOTE**: Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects is deprecated, and will begin throwing an exception
|
||||
> starting with Electron 9.
|
||||
> special Electron objects will throw an exception.
|
||||
|
||||
The renderer process can handle the message by listening to `channel` with the
|
||||
[`ipcRenderer`](ipc-renderer.md) module.
|
||||
@@ -1581,7 +1585,9 @@ app.whenReady().then(() => {
|
||||
|
||||
#### `contents.sendToFrame(frameId, channel, ...args)`
|
||||
|
||||
* `frameId` Integer
|
||||
* `frameId` Integer | [number, number] - the ID of the frame to send to, or a
|
||||
pair of `[processId, frameId]` if the frame is in a different process to the
|
||||
main frame.
|
||||
* `channel` String
|
||||
* `...args` any[]
|
||||
|
||||
@@ -1591,9 +1597,8 @@ Send an asynchronous message to a specific frame in a renderer process via
|
||||
chains will not be included. Sending Functions, Promises, Symbols, WeakMaps, or
|
||||
WeakSets will throw an exception.
|
||||
|
||||
> **NOTE**: Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects is deprecated, and will begin throwing an exception
|
||||
> starting with Electron 9.
|
||||
> **NOTE:** Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
|
||||
The renderer process can handle the message by listening to `channel` with the
|
||||
[`ipcRenderer`](ipc-renderer.md) module.
|
||||
@@ -1755,7 +1760,7 @@ Returns `Boolean` - If *offscreen rendering* is enabled returns whether it is cu
|
||||
* `fps` Integer
|
||||
|
||||
If *offscreen rendering* is enabled sets the frame rate to the specified number.
|
||||
Only values between 1 and 60 are accepted.
|
||||
Only values between 1 and 240 are accepted.
|
||||
|
||||
#### `contents.getFrameRate()`
|
||||
|
||||
@@ -1853,7 +1858,7 @@ The zoom factor is the zoom percent divided by 100, so 300% = 3.0.
|
||||
#### `contents.frameRate`
|
||||
|
||||
An `Integer` property that sets the frame rate of the web contents to the specified number.
|
||||
Only values between 1 and 60 are accepted.
|
||||
Only values between 1 and 240 are accepted.
|
||||
|
||||
Only applicable if *offscreen rendering* is enabled.
|
||||
|
||||
|
||||
@@ -560,9 +560,9 @@ Stops any `findInPage` request for the `webview` with the provided `action`.
|
||||
* `pagesPerSheet` Number (optional) - The number of pages to print per page sheet.
|
||||
* `collate` Boolean (optional) - Whether the web page should be collated.
|
||||
* `copies` Number (optional) - The number of copies of the web page to print.
|
||||
* `pageRanges` Record<string, number> (optional) - The page range to print.
|
||||
* `from` Number - the start page.
|
||||
* `to` Number - the end page.
|
||||
* `pageRanges` Object[] (optional) - The page range to print. On macOS, only the first range is honored.
|
||||
* `from` Number - Index of the first page to print (0-based).
|
||||
* `to` Number - Index of the last page to print (inclusive) (0-based).
|
||||
* `duplexMode` String (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
|
||||
* `dpi` Record<string, number> (optional)
|
||||
* `horizontal` Number (optional) - The horizontal dpi.
|
||||
@@ -588,8 +588,8 @@ Prints `webview`'s web page. Same as `webContents.print([options])`.
|
||||
and `width` in microns.
|
||||
* `scaleFactor` Number (optional) - The scale factor of the web page. Can range from 0 to 100.
|
||||
* `pageRanges` Record<string, number> (optional) - The page range to print.
|
||||
* `from` Number - the first page to print.
|
||||
* `to` Number - the last page to print (inclusive).
|
||||
* `from` Number - Index of the first page to print (0-based).
|
||||
* `to` Number - Index of the last page to print (inclusive) (0-based).
|
||||
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
|
||||
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
# Breaking changes (NetworkService) (Draft)
|
||||
|
||||
This document describes changes to Electron APIs after migrating network code
|
||||
to NetworkService API.
|
||||
|
||||
We don't currently have an estimate of when we will enable `NetworkService` by
|
||||
default in Electron, but as Chromium is already removing non-`NetworkService`
|
||||
code, we might switch before Electron 10.
|
||||
|
||||
The content of this document should be moved to `breaking-changes.md` once we have
|
||||
determined when to enable `NetworkService` in Electron.
|
||||
|
||||
## Planned Breaking API Changes
|
||||
|
||||
### `protocol.unregisterProtocol`
|
||||
### `protocol.uninterceptProtocol`
|
||||
|
||||
The APIs are now synchronous and the optional callback is no longer needed.
|
||||
|
||||
```javascript
|
||||
// Deprecated
|
||||
protocol.unregisterProtocol(scheme, () => { /* ... */ })
|
||||
// Replace with
|
||||
protocol.unregisterProtocol(scheme)
|
||||
```
|
||||
|
||||
### `protocol.registerFileProtocol`
|
||||
### `protocol.registerBufferProtocol`
|
||||
### `protocol.registerStringProtocol`
|
||||
### `protocol.registerHttpProtocol`
|
||||
### `protocol.registerStreamProtocol`
|
||||
### `protocol.interceptFileProtocol`
|
||||
### `protocol.interceptStringProtocol`
|
||||
### `protocol.interceptBufferProtocol`
|
||||
### `protocol.interceptHttpProtocol`
|
||||
### `protocol.interceptStreamProtocol`
|
||||
|
||||
The APIs are now synchronous and the optional callback is no longer needed.
|
||||
|
||||
```javascript
|
||||
// Deprecated
|
||||
protocol.registerFileProtocol(scheme, handler, () => { /* ... */ })
|
||||
// Replace with
|
||||
protocol.registerFileProtocol(scheme, handler)
|
||||
```
|
||||
|
||||
The registered or intercepted protocol does not have effect on current page
|
||||
until navigation happens.
|
||||
|
||||
### `protocol.isProtocolHandled`
|
||||
|
||||
This API is deprecated and users should use `protocol.isProtocolRegistered`
|
||||
and `protocol.isProtocolIntercepted` instead.
|
||||
|
||||
```javascript
|
||||
// Deprecated
|
||||
protocol.isProtocolHandled(scheme).then(() => { /* ... */ })
|
||||
// Replace with
|
||||
const isRegistered = protocol.isProtocolRegistered(scheme)
|
||||
const isIntercepted = protocol.isProtocolIntercepted(scheme)
|
||||
```
|
||||
@@ -124,6 +124,54 @@ const w = new BrowserWindow({
|
||||
We [recommend moving away from the remote
|
||||
module](https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31).
|
||||
|
||||
### `protocol.unregisterProtocol`
|
||||
### `protocol.uninterceptProtocol`
|
||||
|
||||
The APIs are now synchronous and the optional callback is no longer needed.
|
||||
|
||||
```javascript
|
||||
// Deprecated
|
||||
protocol.unregisterProtocol(scheme, () => { /* ... */ })
|
||||
// Replace with
|
||||
protocol.unregisterProtocol(scheme)
|
||||
```
|
||||
|
||||
### `protocol.registerFileProtocol`
|
||||
### `protocol.registerBufferProtocol`
|
||||
### `protocol.registerStringProtocol`
|
||||
### `protocol.registerHttpProtocol`
|
||||
### `protocol.registerStreamProtocol`
|
||||
### `protocol.interceptFileProtocol`
|
||||
### `protocol.interceptStringProtocol`
|
||||
### `protocol.interceptBufferProtocol`
|
||||
### `protocol.interceptHttpProtocol`
|
||||
### `protocol.interceptStreamProtocol`
|
||||
|
||||
The APIs are now synchronous and the optional callback is no longer needed.
|
||||
|
||||
```javascript
|
||||
// Deprecated
|
||||
protocol.registerFileProtocol(scheme, handler, () => { /* ... */ })
|
||||
// Replace with
|
||||
protocol.registerFileProtocol(scheme, handler)
|
||||
```
|
||||
|
||||
The registered or intercepted protocol does not have effect on current page
|
||||
until navigation happens.
|
||||
|
||||
### `protocol.isProtocolHandled`
|
||||
|
||||
This API is deprecated and users should use `protocol.isProtocolRegistered`
|
||||
and `protocol.isProtocolIntercepted` instead.
|
||||
|
||||
```javascript
|
||||
// Deprecated
|
||||
protocol.isProtocolHandled(scheme).then(() => { /* ... */ })
|
||||
// Replace with
|
||||
const isRegistered = protocol.isProtocolRegistered(scheme)
|
||||
const isIntercepted = protocol.isProtocolIntercepted(scheme)
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (9.0)
|
||||
|
||||
### Default Changed: Loading non-context-aware native modules in the renderer process is disabled by default
|
||||
@@ -138,6 +186,45 @@ you should plan to update your native modules to be context aware.
|
||||
|
||||
For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).
|
||||
|
||||
### Deprecated: `BrowserWindow` extension APIs
|
||||
|
||||
The following extension APIs have been deprecated:
|
||||
* `BrowserWindow.addExtension(path)`
|
||||
* `BrowserWindow.addDevToolsExtension(path)`
|
||||
* `BrowserWindow.removeExtension(name)`
|
||||
* `BrowserWindow.removeDevToolsExtension(name)`
|
||||
* `BrowserWindow.getExtensions()`
|
||||
* `BrowserWindow.getDevToolsExtensions()`
|
||||
|
||||
Use the session APIs instead:
|
||||
* `ses.loadExtension(path)`
|
||||
* `ses.removeExtension(extension_id)`
|
||||
* `ses.getAllExtensions()`
|
||||
|
||||
```js
|
||||
// Deprecated in Electron 9
|
||||
BrowserWindow.addExtension(path)
|
||||
BrowserWindow.addDevToolsExtension(path)
|
||||
// Replace with
|
||||
session.defaultSession.loadExtension(path)
|
||||
```
|
||||
|
||||
```js
|
||||
// Deprecated in Electron 9
|
||||
BrowserWindow.removeExtension(name)
|
||||
BrowserWindow.removeDevToolsExtension(name)
|
||||
// Replace with
|
||||
session.defaultSession.removeExtension(extension_id)
|
||||
```
|
||||
|
||||
```js
|
||||
// Deprecated in Electron 9
|
||||
BrowserWindow.getExtensions()
|
||||
BrowserWindow.getDevToolsExtensions()
|
||||
// Replace with
|
||||
session.defaultSession.getAllExtensions()
|
||||
```
|
||||
|
||||
### Removed: `<webview>.getWebContents()`
|
||||
|
||||
This API, which was deprecated in Electron 8.0, is now removed.
|
||||
@@ -281,6 +368,52 @@ in Electron 8.x, and cease to exist in Electron 9.x. The layout zoom level
|
||||
limits are now fixed at a minimum of 0.25 and a maximum of 5.0, as defined
|
||||
[here](https://chromium.googlesource.com/chromium/src/+/938b37a6d2886bf8335fc7db792f1eb46c65b2ae/third_party/blink/common/page/page_zoom.cc#11).
|
||||
|
||||
### Deprecated events in `systemPreferences`
|
||||
|
||||
The following `systemPreferences` events have been deprecated:
|
||||
* `inverted-color-scheme-changed`
|
||||
* `high-contrast-color-scheme-changed`
|
||||
|
||||
Use the new `updated` event on the `nativeTheme` module instead.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
systemPreferences.on('inverted-color-scheme-changed', () => { /* ... */ })
|
||||
systemPreferences.on('high-contrast-color-scheme-changed', () => { /* ... */ })
|
||||
|
||||
// Replace with
|
||||
nativeTheme.on('updated', () => { /* ... */ })
|
||||
```
|
||||
|
||||
### Deprecated: methods in `systemPreferences`
|
||||
|
||||
The following `systemPreferences` methods have been deprecated:
|
||||
* `systemPreferences.isDarkMode()`
|
||||
* `systemPreferences.isInvertedColorScheme()`
|
||||
* `systemPreferences.isHighContrastColorScheme()`
|
||||
|
||||
Use the following `nativeTheme` properties instead:
|
||||
* `nativeTheme.shouldUseDarkColors`
|
||||
* `nativeTheme.shouldUseInvertedColorScheme`
|
||||
* `nativeTheme.shouldUseHighContrastColors`
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
systemPreferences.isDarkMode()
|
||||
// Replace with
|
||||
nativeTheme.shouldUseDarkColors
|
||||
|
||||
// Deprecated
|
||||
systemPreferences.isInvertedColorScheme()
|
||||
// Replace with
|
||||
nativeTheme.shouldUseInvertedColorScheme
|
||||
|
||||
// Deprecated
|
||||
systemPreferences.isHighContrastColorScheme()
|
||||
// Replace with
|
||||
nativeTheme.shouldUseHighContrastColors
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (7.0)
|
||||
|
||||
### Deprecated: Atom.io Node Headers URL
|
||||
|
||||
@@ -173,12 +173,12 @@ $ gn gen out/Testing-x86 --args='... target_cpu = "x86"'
|
||||
|
||||
Not all combinations of source and target CPU/OS are supported by Chromium.
|
||||
|
||||
<table>
|
||||
<tr><th>Host</th><th>Target</th><th>Status</th></tr>
|
||||
<tr><td>Windows x64</td><td>Windows arm64</td><td>Experimental</td>
|
||||
<tr><td>Windows x64</td><td>Windows x86</td><td>Automatically tested</td></tr>
|
||||
<tr><td>Linux x64</td><td>Linux x86</td><td>Automatically tested</td></tr>
|
||||
</table>
|
||||
| Host | Target | Status |
|
||||
|-------------|---------------|----------------------|
|
||||
| Windows x64 | Windows arm64 | Experimental |
|
||||
| Windows x64 | Windows x86 | Automatically tested |
|
||||
| Linux x64 | Linux x86 | Automatically tested |
|
||||
|
||||
|
||||
If you test other combinations and find them to work, please update this document :)
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ $ pip install pyobjc
|
||||
If you're developing Electron and don't plan to redistribute your
|
||||
custom Electron build, you may skip this section.
|
||||
|
||||
Official Electron builds are built with [Xcode 9.4.1](http://adcdownload.apple.com/Developer_Tools/Xcode_9.4.1/Xcode_9.4.1.xip), and the macOS 10.13 SDK. Building with a newer SDK works too, but the releases currently use the 10.13 SDK.
|
||||
Official Electron builds are built with [Xcode 11.1](https://download.developer.apple.com/Developer_Tools/Xcode_11.1/Xcode_11.1.xip), and the macOS 10.15 SDK. Building with a newer SDK works too, but the releases currently use the 10.15 SDK.
|
||||
|
||||
## Building Electron
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@ SRV*c:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*c:\code\sym
|
||||
|
||||
## Using the symbol server in Visual Studio
|
||||
|
||||
<img src='https://mdn.mozillademos.org/files/733/symbol-server-vc8express-menu.jpg'>
|
||||
<img src='https://mdn.mozillademos.org/files/2497/2005_options.gif'>
|
||||

|
||||

|
||||
|
||||
## Troubleshooting: Symbols will not load
|
||||
|
||||
|
||||
@@ -1,95 +1,95 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('open-error-dialog', event => {
|
||||
dialog.showErrorBox('An Error Message', 'Demonstrating an error message.')
|
||||
})
|
||||
|
||||
ipcMain.on('open-information-dialog', event => {
|
||||
const options = {
|
||||
type: 'info',
|
||||
title: 'Information',
|
||||
message: "This is an information dialog. Isn't it nice?",
|
||||
buttons: ['Yes', 'No']
|
||||
}
|
||||
dialog.showMessageBox(options, index => {
|
||||
event.sender.send('information-dialog-selection', index)
|
||||
})
|
||||
})
|
||||
|
||||
ipcMain.on('open-file-dialog', event => {
|
||||
dialog.showOpenDialog(
|
||||
{
|
||||
properties: ['openFile', 'openDirectory']
|
||||
},
|
||||
files => {
|
||||
if (files) {
|
||||
event.sender.send('selected-directory', files)
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
ipcMain.on('save-dialog', event => {
|
||||
const options = {
|
||||
title: 'Save an Image',
|
||||
filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]
|
||||
}
|
||||
dialog.showSaveDialog(options, filename => {
|
||||
event.sender.send('saved-file', filename)
|
||||
})
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('open-error-dialog', event => {
|
||||
dialog.showErrorBox('An Error Message', 'Demonstrating an error message.')
|
||||
})
|
||||
|
||||
ipcMain.on('open-information-dialog', event => {
|
||||
const options = {
|
||||
type: 'info',
|
||||
title: 'Information',
|
||||
message: "This is an information dialog. Isn't it nice?",
|
||||
buttons: ['Yes', 'No']
|
||||
}
|
||||
dialog.showMessageBox(options, index => {
|
||||
event.sender.send('information-dialog-selection', index)
|
||||
})
|
||||
})
|
||||
|
||||
ipcMain.on('open-file-dialog', event => {
|
||||
dialog.showOpenDialog(
|
||||
{
|
||||
properties: ['openFile', 'openDirectory']
|
||||
},
|
||||
files => {
|
||||
if (files) {
|
||||
event.sender.send('selected-directory', files)
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
ipcMain.on('save-dialog', event => {
|
||||
const options = {
|
||||
title: 'Save an Image',
|
||||
filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]
|
||||
}
|
||||
dialog.showSaveDialog(options, filename => {
|
||||
event.sender.send('saved-file', filename)
|
||||
})
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
const { ipcRenderer, shell } = require('electron')
|
||||
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
const errorBtn = document.getElementById('error-dialog')
|
||||
|
||||
errorBtn.addEventListener('click', event => {
|
||||
ipcRenderer.send('open-error-dialog')
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
const { ipcRenderer, shell } = require('electron')
|
||||
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
const errorBtn = document.getElementById('error-dialog')
|
||||
|
||||
errorBtn.addEventListener('click', event => {
|
||||
ipcRenderer.send('open-error-dialog')
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -1,70 +1,70 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
ipcMain.on('open-information-dialog', event => {
|
||||
const options = {
|
||||
type: 'info',
|
||||
title: 'Information',
|
||||
message: "This is an information dialog. Isn't it nice?",
|
||||
buttons: ['Yes', 'No']
|
||||
}
|
||||
dialog.showMessageBox(options, index => {
|
||||
event.sender.send('information-dialog-selection', index)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
ipcMain.on('open-information-dialog', event => {
|
||||
const options = {
|
||||
type: 'info',
|
||||
title: 'Information',
|
||||
message: "This is an information dialog. Isn't it nice?",
|
||||
buttons: ['Yes', 'No']
|
||||
}
|
||||
dialog.showMessageBox(options, index => {
|
||||
event.sender.send('information-dialog-selection', index)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
const { ipcRenderer, shell } = require('electron')
|
||||
|
||||
const informationBtn = document.getElementById('information-dialog')
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
informationBtn.addEventListener('click', event => {
|
||||
ipcRenderer.send('open-information-dialog')
|
||||
})
|
||||
|
||||
ipcRenderer.on('information-dialog-selection', (event, index) => {
|
||||
let message = 'You selected '
|
||||
if (index === 0) message += 'yes.'
|
||||
else message += 'no.'
|
||||
document.getElementById('info-selection').innerHTML = message
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
const { ipcRenderer, shell } = require('electron')
|
||||
|
||||
const informationBtn = document.getElementById('information-dialog')
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
informationBtn.addEventListener('click', event => {
|
||||
ipcRenderer.send('open-information-dialog')
|
||||
})
|
||||
|
||||
ipcRenderer.on('information-dialog-selection', (event, index) => {
|
||||
let message = 'You selected '
|
||||
if (index === 0) message += 'yes.'
|
||||
else message += 'no.'
|
||||
document.getElementById('info-selection').innerHTML = message
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -1,70 +1,70 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
ipcMain.on('open-file-dialog', event => {
|
||||
dialog.showOpenDialog(
|
||||
{
|
||||
properties: ['openFile', 'openDirectory']
|
||||
},
|
||||
files => {
|
||||
if (files) {
|
||||
event.sender.send('selected-directory', files)
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
ipcMain.on('open-file-dialog', event => {
|
||||
dialog.showOpenDialog(
|
||||
{
|
||||
properties: ['openFile', 'openDirectory']
|
||||
},
|
||||
files => {
|
||||
if (files) {
|
||||
event.sender.send('selected-directory', files)
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
const { ipcRenderer, shell } = require('electron')
|
||||
|
||||
const selectDirBtn = document.getElementById('select-directory')
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
selectDirBtn.addEventListener('click', event => {
|
||||
ipcRenderer.send('open-file-dialog')
|
||||
})
|
||||
|
||||
ipcRenderer.on('selected-directory', (event, path) => {
|
||||
document.getElementById('selected-file').innerHTML = `You selected: ${path}`
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
const { ipcRenderer, shell } = require('electron')
|
||||
|
||||
const selectDirBtn = document.getElementById('select-directory')
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
selectDirBtn.addEventListener('click', event => {
|
||||
ipcRenderer.send('open-file-dialog')
|
||||
})
|
||||
|
||||
ipcRenderer.on('selected-directory', (event, path) => {
|
||||
document.getElementById('selected-file').innerHTML = `You selected: ${path}`
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,66 +1,66 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('save-dialog', event => {
|
||||
const options = {
|
||||
title: 'Save an Image',
|
||||
filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]
|
||||
}
|
||||
dialog.showSaveDialog(options, filename => {
|
||||
event.sender.send('saved-file', filename)
|
||||
})
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('save-dialog', event => {
|
||||
const options = {
|
||||
title: 'Save an Image',
|
||||
filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]
|
||||
}
|
||||
dialog.showSaveDialog(options, filename => {
|
||||
event.sender.send('saved-file', filename)
|
||||
})
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
const { ipcRenderer, shell } = require('electron')
|
||||
|
||||
const saveBtn = document.getElementById('save-dialog')
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
saveBtn.addEventListener('click', event => {
|
||||
ipcRenderer.send('save-dialog')
|
||||
})
|
||||
|
||||
ipcRenderer.on('saved-file', (event, path) => {
|
||||
if (!path) path = 'No path'
|
||||
document.getElementById('file-saved').innerHTML = `Path selected: ${path}`
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
const { ipcRenderer, shell } = require('electron')
|
||||
|
||||
const saveBtn = document.getElementById('save-dialog')
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
saveBtn.addEventListener('click', event => {
|
||||
ipcRenderer.send('save-dialog')
|
||||
})
|
||||
|
||||
ipcRenderer.on('saved-file', (event, path) => {
|
||||
if (!path) path = 'No path'
|
||||
document.getElementById('file-saved').innerHTML = `Path selected: ${path}`
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -1,56 +1,56 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
const { shell } = require('electron')
|
||||
const os = require('os')
|
||||
|
||||
const exLinksBtn = document.getElementById('open-ex-links')
|
||||
const fileManagerBtn = document.getElementById('open-file-manager')
|
||||
|
||||
fileManagerBtn.addEventListener('click', (event) => {
|
||||
shell.showItemInFolder(os.homedir())
|
||||
})
|
||||
|
||||
exLinksBtn.addEventListener('click', (event) => {
|
||||
shell.openExternal('https://electronjs.org')
|
||||
const { shell } = require('electron')
|
||||
const os = require('os')
|
||||
|
||||
const exLinksBtn = document.getElementById('open-ex-links')
|
||||
const fileManagerBtn = document.getElementById('open-file-manager')
|
||||
|
||||
fileManagerBtn.addEventListener('click', (event) => {
|
||||
shell.showItemInFolder(os.homedir())
|
||||
})
|
||||
|
||||
exLinksBtn.addEventListener('click', (event) => {
|
||||
shell.openExternal('https://electronjs.org')
|
||||
})
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
const basicNotification = {
|
||||
title: 'Basic Notification',
|
||||
body: 'Short message part'
|
||||
}
|
||||
|
||||
const notification = {
|
||||
title: 'Notification with image',
|
||||
body: 'Short message plus a custom image',
|
||||
icon: 'https://via.placeholder.com/150'
|
||||
}
|
||||
|
||||
const basicNotificationButton = document.getElementById('basic-noti')
|
||||
const notificationButton = document.getElementById('advanced-noti')
|
||||
|
||||
notificationButton.addEventListener('click', () => {
|
||||
const myNotification = new window.Notification(notification.title, notification)
|
||||
|
||||
myNotification.onclick = () => {
|
||||
console.log('Notification clicked')
|
||||
}
|
||||
})
|
||||
|
||||
basicNotificationButton.addEventListener('click', () => {
|
||||
const myNotification = new window.Notification(basicNotification.title, basicNotification)
|
||||
|
||||
myNotification.onclick = () => {
|
||||
console.log('Notification clicked')
|
||||
}
|
||||
})
|
||||
const basicNotification = {
|
||||
title: 'Basic Notification',
|
||||
body: 'Short message part'
|
||||
}
|
||||
|
||||
const notification = {
|
||||
title: 'Notification with image',
|
||||
body: 'Short message plus a custom image',
|
||||
icon: 'https://via.placeholder.com/150'
|
||||
}
|
||||
|
||||
const basicNotificationButton = document.getElementById('basic-noti')
|
||||
const notificationButton = document.getElementById('advanced-noti')
|
||||
|
||||
notificationButton.addEventListener('click', () => {
|
||||
const myNotification = new window.Notification(notification.title, notification)
|
||||
|
||||
myNotification.onclick = () => {
|
||||
console.log('Notification clicked')
|
||||
}
|
||||
})
|
||||
|
||||
basicNotificationButton.addEventListener('click', () => {
|
||||
const myNotification = new window.Notification(basicNotification.title, basicNotification)
|
||||
|
||||
myNotification.onclick = () => {
|
||||
console.log('Notification clicked')
|
||||
}
|
||||
})
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,35 +1,35 @@
|
||||
const { ipcRenderer, shell } = require('electron')
|
||||
|
||||
const trayBtn = document.getElementById('put-in-tray')
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
let trayOn = false
|
||||
|
||||
trayBtn.addEventListener('click', function (event) {
|
||||
if (trayOn) {
|
||||
trayOn = false
|
||||
document.getElementById('tray-countdown').innerHTML = ''
|
||||
ipcRenderer.send('remove-tray')
|
||||
} else {
|
||||
trayOn = true
|
||||
const message = 'Click demo again to remove.'
|
||||
document.getElementById('tray-countdown').innerHTML = message
|
||||
ipcRenderer.send('put-in-tray')
|
||||
}
|
||||
})
|
||||
// Tray removed from context menu on icon
|
||||
ipcRenderer.on('tray-removed', function () {
|
||||
ipcRenderer.send('remove-tray')
|
||||
trayOn = false
|
||||
document.getElementById('tray-countdown').innerHTML = ''
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
const { ipcRenderer, shell } = require('electron')
|
||||
|
||||
const trayBtn = document.getElementById('put-in-tray')
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
let trayOn = false
|
||||
|
||||
trayBtn.addEventListener('click', function (event) {
|
||||
if (trayOn) {
|
||||
trayOn = false
|
||||
document.getElementById('tray-countdown').innerHTML = ''
|
||||
ipcRenderer.send('remove-tray')
|
||||
} else {
|
||||
trayOn = true
|
||||
const message = 'Click demo again to remove.'
|
||||
document.getElementById('tray-countdown').innerHTML = message
|
||||
ipcRenderer.send('put-in-tray')
|
||||
}
|
||||
})
|
||||
// Tray removed from context menu on icon
|
||||
ipcRenderer.on('tray-removed', function () {
|
||||
ipcRenderer.send('remove-tray')
|
||||
trayOn = false
|
||||
document.getElementById('tray-countdown').innerHTML = ''
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -1,56 +1,56 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
const { BrowserWindow } = require('electron').remote
|
||||
const shell = require('electron').shell
|
||||
|
||||
const framelessWindowBtn = document.getElementById('frameless-window')
|
||||
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
framelessWindowBtn.addEventListener('click', (event) => {
|
||||
const modalPath = 'https://electronjs.org'
|
||||
let win = new BrowserWindow({ frame: false })
|
||||
|
||||
win.on('close', () => { win = null })
|
||||
win.loadURL(modalPath)
|
||||
win.show()
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
const { BrowserWindow } = require('electron').remote
|
||||
const shell = require('electron').shell
|
||||
|
||||
const framelessWindowBtn = document.getElementById('frameless-window')
|
||||
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
framelessWindowBtn.addEventListener('click', (event) => {
|
||||
const modalPath = 'https://electronjs.org'
|
||||
let win = new BrowserWindow({ frame: false })
|
||||
|
||||
win.on('close', () => { win = null })
|
||||
win.loadURL(modalPath)
|
||||
win.show()
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
const { BrowserWindow } = require('electron').remote
|
||||
const shell = require('electron').shell
|
||||
|
||||
const manageWindowBtn = document.getElementById('manage-window')
|
||||
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
let win
|
||||
|
||||
manageWindowBtn.addEventListener('click', (event) => {
|
||||
const modalPath = 'https://electronjs.org'
|
||||
win = new BrowserWindow({ width: 400, height: 275 })
|
||||
|
||||
win.on('resize', updateReply)
|
||||
win.on('move', updateReply)
|
||||
win.on('close', () => { win = null })
|
||||
win.loadURL(modalPath)
|
||||
win.show()
|
||||
|
||||
function updateReply () {
|
||||
const manageWindowReply = document.getElementById('manage-window-reply')
|
||||
const message = `Size: ${win.getSize()} Position: ${win.getPosition()}`
|
||||
manageWindowReply.innerText = message
|
||||
}
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
const { BrowserWindow } = require('electron').remote
|
||||
const shell = require('electron').shell
|
||||
|
||||
const manageWindowBtn = document.getElementById('manage-window')
|
||||
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
let win
|
||||
|
||||
manageWindowBtn.addEventListener('click', (event) => {
|
||||
const modalPath = 'https://electronjs.org'
|
||||
win = new BrowserWindow({ width: 400, height: 275 })
|
||||
|
||||
win.on('resize', updateReply)
|
||||
win.on('move', updateReply)
|
||||
win.on('close', () => { win = null })
|
||||
win.loadURL(modalPath)
|
||||
win.show()
|
||||
|
||||
function updateReply () {
|
||||
const manageWindowReply = document.getElementById('manage-window-reply')
|
||||
const message = `Size: ${win.getSize()} Position: ${win.getPosition()}`
|
||||
manageWindowReply.innerText = message
|
||||
}
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
const { BrowserWindow } = require('electron').remote
|
||||
const shell = require('electron').shell
|
||||
|
||||
const listenToWindowBtn = document.getElementById('listen-to-window')
|
||||
const focusModalBtn = document.getElementById('focus-on-modal-window')
|
||||
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
let win
|
||||
|
||||
listenToWindowBtn.addEventListener('click', () => {
|
||||
const modalPath = 'https://electronjs.org'
|
||||
win = new BrowserWindow({ width: 600, height: 400 })
|
||||
|
||||
const hideFocusBtn = () => {
|
||||
focusModalBtn.classList.add('disappear')
|
||||
focusModalBtn.classList.remove('smooth-appear')
|
||||
focusModalBtn.removeEventListener('click', clickHandler)
|
||||
}
|
||||
|
||||
const showFocusBtn = (btn) => {
|
||||
if (!win) return
|
||||
focusModalBtn.classList.add('smooth-appear')
|
||||
focusModalBtn.classList.remove('disappear')
|
||||
focusModalBtn.addEventListener('click', clickHandler)
|
||||
}
|
||||
|
||||
win.on('focus', hideFocusBtn)
|
||||
win.on('blur', showFocusBtn)
|
||||
win.on('close', () => {
|
||||
hideFocusBtn()
|
||||
win = null
|
||||
})
|
||||
win.loadURL(modalPath)
|
||||
win.show()
|
||||
|
||||
const clickHandler = () => { win.focus() }
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
const { BrowserWindow } = require('electron').remote
|
||||
const shell = require('electron').shell
|
||||
|
||||
const listenToWindowBtn = document.getElementById('listen-to-window')
|
||||
const focusModalBtn = document.getElementById('focus-on-modal-window')
|
||||
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
let win
|
||||
|
||||
listenToWindowBtn.addEventListener('click', () => {
|
||||
const modalPath = 'https://electronjs.org'
|
||||
win = new BrowserWindow({ width: 600, height: 400 })
|
||||
|
||||
const hideFocusBtn = () => {
|
||||
focusModalBtn.classList.add('disappear')
|
||||
focusModalBtn.classList.remove('smooth-appear')
|
||||
focusModalBtn.removeEventListener('click', clickHandler)
|
||||
}
|
||||
|
||||
const showFocusBtn = (btn) => {
|
||||
if (!win) return
|
||||
focusModalBtn.classList.add('smooth-appear')
|
||||
focusModalBtn.classList.remove('disappear')
|
||||
focusModalBtn.addEventListener('click', clickHandler)
|
||||
}
|
||||
|
||||
win.on('focus', hideFocusBtn)
|
||||
win.on('blur', showFocusBtn)
|
||||
win.on('close', () => {
|
||||
hideFocusBtn()
|
||||
win = null
|
||||
})
|
||||
win.loadURL(modalPath)
|
||||
win.show()
|
||||
|
||||
const clickHandler = () => { win.focus() }
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
# DevTools Extension
|
||||
|
||||
Electron supports the [Chrome DevTools Extension][devtools-extension], which can
|
||||
be used to extend the ability of devtools for debugging popular web frameworks.
|
||||
Electron supports [Chrome DevTools extensions][devtools-extension], which can
|
||||
be used to extend the ability of Chrome's developer tools for debugging
|
||||
popular web frameworks.
|
||||
|
||||
## How to load a DevTools Extension
|
||||
## Loading a DevTools extension with tooling
|
||||
|
||||
This document outlines the process for manually loading an extension.
|
||||
You may also try
|
||||
[electron-devtools-installer](https://github.com/GPMDP/electron-devtools-installer),
|
||||
a third-party tool that downloads extensions directly from the Chrome WebStore.
|
||||
The easiest way to load a DevTools extension is to use third-party tooling to automate the
|
||||
process for you. [electron-devtools-installer][electron-devtools-installer] is a popular
|
||||
NPM package that does just that.
|
||||
|
||||
To load an extension in Electron, you need to download it in Chrome browser,
|
||||
locate its filesystem path, and then load it by calling the
|
||||
`BrowserWindow.addDevToolsExtension(extension)` API.
|
||||
## Manually loading a DevTools extension
|
||||
|
||||
Using the [React Developer Tools][react-devtools] as example:
|
||||
If you don't want to use the tooling approach, you can also do all of the necessary
|
||||
operations by hand. To load an extension in Electron, you need to download it via Chrome,
|
||||
locate its filesystem path, and then load it into your [Session][session] by calling the
|
||||
[`ses.loadExtension`] API.
|
||||
|
||||
1. Install it in Chrome browser.
|
||||
Using the [React Developer Tools][react-devtools] as an example:
|
||||
|
||||
1. Install the extension in Google Chrome.
|
||||
1. Navigate to `chrome://extensions`, and find its extension ID, which is a hash
|
||||
string like `fmkadmapgofadopljbjfkapdkoienihi`.
|
||||
1. Find out filesystem location used by Chrome for storing extensions:
|
||||
1. Find out the filesystem location used by Chrome for storing extensions:
|
||||
* on Windows it is `%LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensions`;
|
||||
* on Linux it could be:
|
||||
* `~/.config/google-chrome/Default/Extensions/`
|
||||
@@ -27,36 +30,48 @@ Using the [React Developer Tools][react-devtools] as example:
|
||||
* `~/.config/google-chrome-canary/Default/Extensions/`
|
||||
* `~/.config/chromium/Default/Extensions/`
|
||||
* on macOS it is `~/Library/Application Support/Google/Chrome/Default/Extensions`.
|
||||
1. Pass the location of the extension to `BrowserWindow.addDevToolsExtension`
|
||||
API, for the React Developer Tools, it is something like:
|
||||
1. Pass the location of the extension to the [`ses.loadExtension`][load-extension]
|
||||
API. For React Developer Tools `v4.9.0`, it looks something like:
|
||||
```javascript
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
const { app, session } = require('electron')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
|
||||
BrowserWindow.addDevToolsExtension(
|
||||
path.join(os.homedir(), '/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.3.0_0')
|
||||
)
|
||||
// on macOS
|
||||
const reactDevToolsPath = path.join(
|
||||
os.homedir(),
|
||||
'/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.9.0_0'
|
||||
)
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
await session.defaultSession.loadExtension(reactDevToolsPath)
|
||||
})
|
||||
```
|
||||
|
||||
**Note:** The `BrowserWindow.addDevToolsExtension` API cannot be called before the
|
||||
ready event of the app module is emitted.
|
||||
**Notes:**
|
||||
|
||||
The extension will be remembered so you only need to call this API once per
|
||||
extension. If you try to add an extension that has already been loaded, this method
|
||||
will not return and instead log a warning to the console.
|
||||
* `loadExtension` returns a Promise with an [Extension object][extension-structure],
|
||||
which contains metadata about the extension that was loaded. This promise needs to
|
||||
resolve (e.g. with an `await` expression) before loading a page. Otherwise, the
|
||||
extension won't be guaranteed to load.
|
||||
* `loadExtension` cannot be called before the `ready` event of the `app` module
|
||||
is emitted, nor can it be called on in-memory (non-persistent) sessions.
|
||||
* `loadExtension` must be called on every boot of your app if you want the
|
||||
extension to be loaded.
|
||||
|
||||
### How to remove a DevTools Extension
|
||||
### Removing a DevTools extension
|
||||
|
||||
You can pass the name of the extension to the `BrowserWindow.removeDevToolsExtension`
|
||||
API to remove it. The name of the extension is returned by
|
||||
`BrowserWindow.addDevToolsExtension` and you can get the names of all installed
|
||||
DevTools Extensions using the `BrowserWindow.getDevToolsExtensions` API.
|
||||
You can pass the extension's ID to the [`ses.removeExtension`][remove-extension] API to
|
||||
remove it from your Session. Loaded extensions are not persisted between
|
||||
app launches.
|
||||
|
||||
## Supported DevTools Extensions
|
||||
## DevTools extension support
|
||||
|
||||
Electron only supports a limited set of `chrome.*` APIs, so some extensions
|
||||
using unsupported `chrome.*` APIs for chrome extension features may not work.
|
||||
Following Devtools Extensions are tested and guaranteed to work in Electron:
|
||||
Electron only supports
|
||||
[a limited set of `chrome.*` APIs][supported-extension-apis],
|
||||
so extensions using unsupported `chrome.*` APIs under the hood may not work.
|
||||
|
||||
The following Devtools extensions have been tested to work in Electron:
|
||||
|
||||
* [Ember Inspector](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi)
|
||||
* [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi)
|
||||
@@ -68,14 +83,22 @@ Following Devtools Extensions are tested and guaranteed to work in Electron:
|
||||
* [Redux DevTools Extension](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd)
|
||||
* [MobX Developer Tools](https://chrome.google.com/webstore/detail/mobx-developer-tools/pfgnfdagidkfgccljigdamigbcnndkod)
|
||||
|
||||
### What should I do if a DevTools Extension is not working?
|
||||
### What should I do if a DevTools extension is not working?
|
||||
|
||||
First please make sure the extension is still being maintained, some extensions
|
||||
can not even work for recent versions of Chrome browser, and we are not able to
|
||||
do anything for them.
|
||||
First, please make sure the extension is still being maintained and is compatible
|
||||
with the latest version of Google Chrome. We cannot provide additional support for
|
||||
unsupported extensions.
|
||||
|
||||
Then file a bug at Electron's issues list, and describe which part of the
|
||||
extension is not working as expected.
|
||||
If the extension works on Chrome but not on Electron, file a bug in Electron's
|
||||
[issue tracker][issue-tracker] and describe which part
|
||||
of the extension is not working as expected.
|
||||
|
||||
[devtools-extension]: https://developer.chrome.com/extensions/devtools
|
||||
[session]: ../api/session.md
|
||||
[react-devtools]: https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi
|
||||
[load-extension]: ../api/session.md#sesloadextensionpath
|
||||
[extension-structure]: ../api/structures/extension.md
|
||||
[remove-extension]: ../api/session.md#sesremoveextensionextensionid
|
||||
[electron-devtools-installer]: https://github.com/MarshallOfSound/electron-devtools-installer
|
||||
[supported-extension-apis]: ../api/extensions.md
|
||||
[issue-tracker]: https://github.com/electron/electron/issues
|
||||
|
||||
@@ -9,7 +9,7 @@ Two modes of rendering can be used and only the dirty area is passed in the
|
||||
`'paint'` event to be more efficient. The rendering can be stopped, continued
|
||||
and the frame rate can be set. The specified frame rate is a top limit value,
|
||||
when there is nothing happening on a webpage, no frames are generated. The
|
||||
maximum frame rate is 60, because above that there is no benefit, only
|
||||
maximum frame rate is 240, because above that there is no benefit, only
|
||||
performance loss.
|
||||
|
||||
**Note:** An offscreen window is always created as a [Frameless Window](../api/frameless-window.md).
|
||||
|
||||
@@ -9,8 +9,12 @@ If you're looking for programming help,
|
||||
for answers to questions,
|
||||
or to join in discussion with other developers who use Electron,
|
||||
you can interact with the community in these locations:
|
||||
- [`electron`](https://discuss.atom.io/c/electron) category on the Atom
|
||||
forums
|
||||
- [`Electron's Discord`](https://discord.com/invite/electron) has channels for:
|
||||
- Getting help
|
||||
- Ecosystem apps like [Electron Forge](https://github.com/electron-userland/electron-forge) and [Electron Fiddle](https://github.com/electron/fiddle)
|
||||
- Sharing ideas with other Electron app developers
|
||||
- And more!
|
||||
- [`electron`](https://discuss.atom.io/c/electron) category on the Atom forums
|
||||
- `#atom-shell` channel on Freenode
|
||||
- `#electron` channel on [Atom's Slack](https://discuss.atom.io/t/join-us-on-slack/16638?source_topic_id=25406)
|
||||
- [`electron-ru`](https://telegram.me/electron_ru) *(Russian)*
|
||||
|
||||
@@ -55,12 +55,15 @@ template("electron_extra_paks") {
|
||||
output = "${invoker.output_dir}/resources.pak"
|
||||
sources = [
|
||||
"$root_gen_dir/components/components_resources.pak",
|
||||
"$root_gen_dir/content/browser/resources/media/media_internals_resources.pak",
|
||||
"$root_gen_dir/content/browser/tracing/tracing_resources.pak",
|
||||
"$root_gen_dir/content/browser/webrtc/resources/webrtc_internals_resources.pak",
|
||||
"$root_gen_dir/content/content_resources.pak",
|
||||
"$root_gen_dir/content/dev_ui_content_resources.pak",
|
||||
"$root_gen_dir/mojo/public/js/mojo_bindings_resources.pak",
|
||||
"$root_gen_dir/net/net_resources.pak",
|
||||
"$root_gen_dir/third_party/blink/public/resources/blink_resources.pak",
|
||||
"$root_gen_dir/third_party/blink/public/resources/inspector_overlay_resources.pak",
|
||||
"$root_gen_dir/ui/resources/webui_resources.pak",
|
||||
"$target_gen_dir/electron_resources.pak",
|
||||
]
|
||||
@@ -68,10 +71,13 @@ template("electron_extra_paks") {
|
||||
"//components/resources",
|
||||
"//content:content_resources",
|
||||
"//content:dev_ui_content_resources",
|
||||
"//content/browser/resources/media:media_internals_resources",
|
||||
"//content/browser/tracing:resources",
|
||||
"//content/browser/webrtc/resources",
|
||||
"//electron:resources",
|
||||
"//mojo/public/js:resources",
|
||||
"//net:net_resources",
|
||||
"//third_party/blink/public:devtools_inspector_resources",
|
||||
"//third_party/blink/public:resources",
|
||||
"//ui/resources",
|
||||
]
|
||||
@@ -86,6 +92,10 @@ template("electron_extra_paks") {
|
||||
sources +=
|
||||
[ "$root_gen_dir/content/browser/devtools/devtools_resources.pak" ]
|
||||
deps += [ "//content/browser/devtools:devtools_resources" ]
|
||||
if (enable_pdf_viewer) {
|
||||
sources += [ "$root_gen_dir/chrome/print_preview_pdf_resources.pak" ]
|
||||
deps += [ "//chrome/browser/resources:print_preview_pdf_resources" ]
|
||||
}
|
||||
if (enable_print_preview) {
|
||||
sources += [ "$root_gen_dir/chrome/print_preview_resources.pak" ]
|
||||
deps += [ "//chrome/browser/resources:print_preview_resources" ]
|
||||
|
||||
@@ -75,4 +75,9 @@
|
||||
<message name="IDS_ACCEPT_LANGUAGES" use_name_for_id="true">
|
||||
en-US,en
|
||||
</message>
|
||||
<if expr="is_win">
|
||||
<message name="IDS_UTILITY_PROCESS_UTILITY_WIN_NAME" desc="The name of the utility process used to handle Windows utility operations.">
|
||||
Windows Utilities
|
||||
</message>
|
||||
</if>
|
||||
</grit-part>
|
||||
|
||||
@@ -43,7 +43,6 @@ auto_filenames = {
|
||||
"docs/api/power-monitor.md",
|
||||
"docs/api/power-save-blocker.md",
|
||||
"docs/api/process.md",
|
||||
"docs/api/protocol-ns.md",
|
||||
"docs/api/protocol.md",
|
||||
"docs/api/remote.md",
|
||||
"docs/api/sandbox-option.md",
|
||||
@@ -120,8 +119,6 @@ auto_filenames = {
|
||||
"docs/api/structures/shared-worker-info.md",
|
||||
"docs/api/structures/shortcut-details.md",
|
||||
"docs/api/structures/size.md",
|
||||
"docs/api/structures/stream-protocol-response.md",
|
||||
"docs/api/structures/string-protocol-response.md",
|
||||
"docs/api/structures/task.md",
|
||||
"docs/api/structures/thumbar-button.md",
|
||||
"docs/api/structures/trace-categories-and-options.md",
|
||||
@@ -139,7 +136,6 @@ auto_filenames = {
|
||||
"lib/common/api/clipboard.js",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
@@ -150,6 +146,7 @@ auto_filenames = {
|
||||
"lib/renderer/api/crash-reporter.ts",
|
||||
"lib/renderer/api/desktop-capturer.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/native-image.ts",
|
||||
"lib/renderer/api/remote.js",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/inspector.ts",
|
||||
@@ -205,8 +202,9 @@ auto_filenames = {
|
||||
"lib/browser/api/menu.js",
|
||||
"lib/browser/api/message-channel.ts",
|
||||
"lib/browser/api/module-list.ts",
|
||||
"lib/browser/api/native-image.ts",
|
||||
"lib/browser/api/native-theme.ts",
|
||||
"lib/browser/api/net-log.js",
|
||||
"lib/browser/api/net-log.ts",
|
||||
"lib/browser/api/net.ts",
|
||||
"lib/browser/api/notification.js",
|
||||
"lib/browser/api/power-monitor.ts",
|
||||
@@ -241,7 +239,6 @@ auto_filenames = {
|
||||
"lib/common/api/clipboard.js",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
@@ -263,7 +260,6 @@ auto_filenames = {
|
||||
"lib/common/api/clipboard.js",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
@@ -278,6 +274,7 @@ auto_filenames = {
|
||||
"lib/renderer/api/exports/electron.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/native-image.ts",
|
||||
"lib/renderer/api/remote.js",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/init.ts",
|
||||
@@ -305,7 +302,6 @@ auto_filenames = {
|
||||
"lib/common/api/clipboard.js",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
@@ -319,6 +315,7 @@ auto_filenames = {
|
||||
"lib/renderer/api/exports/electron.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/native-image.ts",
|
||||
"lib/renderer/api/remote.js",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
|
||||
@@ -184,8 +184,12 @@ filenames = {
|
||||
"shell/browser/electron_web_ui_controller_factory.h",
|
||||
"shell/browser/event_emitter_mixin.cc",
|
||||
"shell/browser/event_emitter_mixin.h",
|
||||
"shell/browser/extended_web_contents_observer.h",
|
||||
"shell/browser/feature_list.cc",
|
||||
"shell/browser/feature_list.h",
|
||||
"shell/browser/file_select_helper.cc",
|
||||
"shell/browser/file_select_helper.h",
|
||||
"shell/browser/file_select_helper_mac.mm",
|
||||
"shell/browser/font_defaults.cc",
|
||||
"shell/browser/font_defaults.h",
|
||||
"shell/browser/javascript_environment.cc",
|
||||
@@ -345,6 +349,7 @@ filenames = {
|
||||
"shell/browser/ui/devtools_manager_delegate.h",
|
||||
"shell/browser/ui/devtools_ui.cc",
|
||||
"shell/browser/ui/devtools_ui.h",
|
||||
"shell/browser/ui/drag_util.cc",
|
||||
"shell/browser/ui/drag_util.h",
|
||||
"shell/browser/ui/drag_util_mac.mm",
|
||||
"shell/browser/ui/drag_util_views.cc",
|
||||
@@ -451,6 +456,7 @@ filenames = {
|
||||
"shell/common/api/electron_api_native_image.cc",
|
||||
"shell/common/api/electron_api_native_image.h",
|
||||
"shell/common/api/electron_api_native_image_mac.mm",
|
||||
"shell/common/api/electron_api_native_image_win.cc",
|
||||
"shell/common/api/electron_api_shell.cc",
|
||||
"shell/common/api/electron_api_v8_util.cc",
|
||||
"shell/common/api/electron_bindings.cc",
|
||||
@@ -525,6 +531,8 @@ filenames = {
|
||||
"shell/common/gin_helper/function_template_extensions.h",
|
||||
"shell/common/gin_helper/locker.cc",
|
||||
"shell/common/gin_helper/locker.h",
|
||||
"shell/common/gin_helper/microtasks_scope.cc",
|
||||
"shell/common/gin_helper/microtasks_scope.h",
|
||||
"shell/common/gin_helper/object_template_builder.cc",
|
||||
"shell/common/gin_helper/object_template_builder.h",
|
||||
"shell/common/gin_helper/persistent_dictionary.cc",
|
||||
@@ -623,6 +631,8 @@ filenames = {
|
||||
"shell/browser/extensions/api/resources_private/resources_private_api.h",
|
||||
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.cc",
|
||||
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.h",
|
||||
"shell/browser/extensions/api/management/electron_management_api_delegate.cc",
|
||||
"shell/browser/extensions/api/management/electron_management_api_delegate.h",
|
||||
"shell/browser/extensions/api/tabs/tabs_api.cc",
|
||||
"shell/browser/extensions/api/tabs/tabs_api.h",
|
||||
"shell/browser/extensions/api/streams_private/streams_private_api.cc",
|
||||
|
||||
@@ -135,6 +135,10 @@ for (const name of events) {
|
||||
});
|
||||
}
|
||||
|
||||
app.on('-session-created' as any, (event, session) => {
|
||||
app.emit('session-created', session);
|
||||
});
|
||||
|
||||
// Deprecate allowRendererProcessReuse but only if they set it to false, no need to log if
|
||||
// they are setting it to true
|
||||
deprecate.removeProperty(app, 'allowRendererProcessReuse', [false]);
|
||||
|
||||
@@ -30,9 +30,11 @@ BrowserWindow.prototype._init = function () {
|
||||
// Though this hack is only needed on macOS when the app is launched from
|
||||
// Finder, we still do it on all platforms in case of other bugs we don't
|
||||
// know.
|
||||
this.webContents.once('load-url', function () {
|
||||
this.focus();
|
||||
});
|
||||
if (this.webContents._initiallyShown) {
|
||||
this.webContents.once('load-url', function () {
|
||||
this.focus();
|
||||
});
|
||||
}
|
||||
|
||||
// Redirect focus/blur event to app instance too.
|
||||
this.on('blur', (event) => {
|
||||
|
||||
@@ -249,7 +249,11 @@ module.exports = {
|
||||
},
|
||||
|
||||
showCertificateTrustDialog: function (window, options) {
|
||||
if (window && window.constructor !== BrowserWindow) options = window;
|
||||
if (window && window.constructor !== BrowserWindow) {
|
||||
options = window;
|
||||
window = null;
|
||||
}
|
||||
|
||||
if (options == null || typeof options !== 'object') {
|
||||
throw new TypeError('options must be an object');
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ const roles = {
|
||||
about: {
|
||||
get label () {
|
||||
return isLinux ? 'About' : `About ${app.name}`;
|
||||
}
|
||||
},
|
||||
...(isWindows && { appMethod: 'showAboutPanel' })
|
||||
},
|
||||
close: {
|
||||
label: isMac ? 'Close Window' : 'Close',
|
||||
@@ -70,7 +71,7 @@ const roles = {
|
||||
},
|
||||
pasteandmatchstyle: {
|
||||
label: 'Paste and Match Style',
|
||||
accelerator: 'Shift+CommandOrControl+V',
|
||||
accelerator: isMac ? 'Cmd+Option+Shift+V' : 'Shift+CommandOrControl+V',
|
||||
webContentsMethod: 'pasteAndMatchStyle',
|
||||
registerAccelerator: false
|
||||
},
|
||||
|
||||
@@ -160,8 +160,14 @@ function sortGroups (groups) {
|
||||
}
|
||||
|
||||
function sortMenuItems (menuItems) {
|
||||
const isSeparator = (item) => item.type === 'separator';
|
||||
const separators = menuItems.filter(i => i.type === 'separator');
|
||||
const isSeparator = (opts) => {
|
||||
return opts.type === 'separator' &&
|
||||
!opts.before &&
|
||||
!opts.after &&
|
||||
!opts.beforeGroupContaining &&
|
||||
!opts.afterGroupContaining;
|
||||
};
|
||||
const separators = menuItems.filter(isSeparator);
|
||||
|
||||
// Split the items into their implicit groups based upon separators.
|
||||
const groups = splitArray(menuItems, isSeparator);
|
||||
|
||||
@@ -182,11 +182,11 @@ Menu.buildFromTemplate = function (template) {
|
||||
throw new TypeError('Invalid template for MenuItem: must have at least one of label, role or type');
|
||||
}
|
||||
|
||||
const filtered = removeExtraSeparators(template);
|
||||
const sorted = sortTemplate(filtered);
|
||||
const sorted = sortTemplate(template);
|
||||
const filtered = removeExtraSeparators(sorted);
|
||||
|
||||
const menu = new Menu();
|
||||
sorted.forEach(item => {
|
||||
filtered.forEach(item => {
|
||||
if (item instanceof MenuItem) {
|
||||
menu.append(item);
|
||||
} else {
|
||||
|
||||
@@ -15,6 +15,7 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'Menu', loader: () => require('./menu') },
|
||||
{ name: 'MenuItem', loader: () => require('./menu-item') },
|
||||
{ name: 'MessageChannelMain', loader: () => require('./message-channel') },
|
||||
{ name: 'nativeImage', loader: () => require('./native-image') },
|
||||
{ name: 'nativeTheme', loader: () => require('./native-theme') },
|
||||
{ name: 'net', loader: () => require('./net') },
|
||||
{ name: 'netLog', loader: () => require('./net-log') },
|
||||
|
||||
@@ -17,6 +17,7 @@ export const browserModuleNames = [
|
||||
'inAppPurchase',
|
||||
'Menu',
|
||||
'MenuItem',
|
||||
'nativeImage',
|
||||
'nativeTheme',
|
||||
'net',
|
||||
'netLog',
|
||||
|
||||
3
lib/browser/api/native-image.ts
Normal file
3
lib/browser/api/native-image.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
const { nativeImage } = process._linkedBinding('electron_common_native_image');
|
||||
|
||||
export default nativeImage;
|
||||
@@ -1,32 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
// TODO(deepak1556): Deprecate and remove standalone netLog module,
|
||||
// it is now a property of session module.
|
||||
const { app, session } = require('electron');
|
||||
|
||||
// Fallback to default session.
|
||||
Object.setPrototypeOf(module.exports, new Proxy({}, {
|
||||
get (target, property) {
|
||||
if (!app.isReady()) return;
|
||||
|
||||
const netLog = session.defaultSession.netLog;
|
||||
|
||||
if (!Object.prototype.hasOwnProperty.call(Object.getPrototypeOf(netLog), property)) return;
|
||||
|
||||
// check for properties on the prototype chain that aren't functions
|
||||
if (typeof netLog[property] !== 'function') return netLog[property];
|
||||
|
||||
// Returning a native function directly would throw error.
|
||||
return (...args) => netLog[property](...args);
|
||||
},
|
||||
|
||||
ownKeys () {
|
||||
if (!app.isReady()) return [];
|
||||
|
||||
return Object.getOwnPropertyNames(Object.getPrototypeOf(session.defaultSession.netLog));
|
||||
},
|
||||
|
||||
getOwnPropertyDescriptor (target) {
|
||||
return { configurable: true, enumerable: true };
|
||||
}
|
||||
}));
|
||||
22
lib/browser/api/net-log.ts
Normal file
22
lib/browser/api/net-log.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
// TODO(deepak1556): Deprecate and remove standalone netLog module,
|
||||
// it is now a property of session module.
|
||||
import { app, session } from 'electron';
|
||||
|
||||
const startLogging: typeof session.defaultSession.netLog.startLogging = async (path, options) => {
|
||||
if (!app.isReady()) return;
|
||||
return session.defaultSession.netLog.startLogging(path, options);
|
||||
};
|
||||
|
||||
const stopLogging: typeof session.defaultSession.netLog.stopLogging = async () => {
|
||||
if (!app.isReady()) return;
|
||||
return session.defaultSession.netLog.stopLogging();
|
||||
};
|
||||
|
||||
export default {
|
||||
startLogging,
|
||||
stopLogging,
|
||||
get currentlyLogging (): boolean {
|
||||
if (!app.isReady()) return false;
|
||||
return session.defaultSession.netLog.currentlyLogging;
|
||||
}
|
||||
};
|
||||
@@ -16,7 +16,7 @@ if ('getAppLevelAppearance' in systemPreferences) {
|
||||
}
|
||||
|
||||
if ('getEffectiveAppearance' in systemPreferences) {
|
||||
const nativeEAGetter = systemPreferences.getAppLevelAppearance;
|
||||
const nativeEAGetter = systemPreferences.getEffectiveAppearance;
|
||||
Object.defineProperty(SystemPreferences.prototype, 'effectiveAppearance', {
|
||||
get: () => nativeEAGetter.call(systemPreferences)
|
||||
});
|
||||
|
||||
@@ -45,7 +45,7 @@ Object.defineProperty(TopLevelWindow.prototype, 'kiosk', {
|
||||
});
|
||||
|
||||
Object.defineProperty(TopLevelWindow.prototype, 'documentEdited', {
|
||||
get: function () { return this.isFullscreen(); },
|
||||
get: function () { return this.isDocumentEdited(); },
|
||||
set: function (edited) { this.setDocumentEdited(edited); }
|
||||
});
|
||||
|
||||
|
||||
@@ -64,6 +64,19 @@ const PDFPageSizes = {
|
||||
}
|
||||
};
|
||||
|
||||
// The minimum micron size Chromium accepts is that where:
|
||||
// Per printing/units.h:
|
||||
// * kMicronsPerInch - Length of an inch in 0.001mm unit.
|
||||
// * kPointsPerInch - Length of an inch in CSS's 1pt unit.
|
||||
//
|
||||
// Formula: (kPointsPerInch / kMicronsPerInch) * size >= 1
|
||||
//
|
||||
// Practically, this means microns need to be > 352 microns.
|
||||
// We therefore need to verify this or it will silently fail.
|
||||
const isValidCustomPageSize = (width, height) => {
|
||||
return [width, height].every(x => x > 352);
|
||||
};
|
||||
|
||||
// Default printing setting
|
||||
const defaultPrintingSetting = {
|
||||
// Customizable.
|
||||
@@ -154,29 +167,29 @@ WebContents.prototype._sendInternalToAll = function (channel, ...args) {
|
||||
|
||||
return this._send(internal, sendToAll, channel, args);
|
||||
};
|
||||
WebContents.prototype.sendToFrame = function (frameId, channel, ...args) {
|
||||
WebContents.prototype.sendToFrame = function (frame, channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument');
|
||||
} else if (typeof frameId !== 'number') {
|
||||
throw new Error('Missing required frameId argument');
|
||||
} else if (!(typeof frame === 'number' || Array.isArray(frame))) {
|
||||
throw new Error('Missing required frame argument (must be number or array)');
|
||||
}
|
||||
|
||||
const internal = false;
|
||||
const sendToAll = false;
|
||||
|
||||
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
|
||||
return this._sendToFrame(internal, sendToAll, frame, channel, args);
|
||||
};
|
||||
WebContents.prototype._sendToFrameInternal = function (frameId, channel, ...args) {
|
||||
WebContents.prototype._sendToFrameInternal = function (frame, channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument');
|
||||
} else if (typeof frameId !== 'number') {
|
||||
throw new Error('Missing required frameId argument');
|
||||
} else if (!(typeof frame === 'number' || Array.isArray(frame))) {
|
||||
throw new Error('Missing required frame argument (must be number or array)');
|
||||
}
|
||||
|
||||
const internal = true;
|
||||
const sendToAll = false;
|
||||
|
||||
return this._sendToFrame(internal, sendToAll, frameId, channel, args);
|
||||
return this._sendToFrame(internal, sendToAll, frame, channel, args);
|
||||
};
|
||||
|
||||
// Following methods are mapped to webFrame.
|
||||
@@ -215,7 +228,9 @@ WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (code, h
|
||||
};
|
||||
|
||||
// Translate the options of printToPDF.
|
||||
WebContents.prototype.printToPDF = function (options) {
|
||||
|
||||
let pendingPromise;
|
||||
WebContents.prototype.printToPDF = async function (options) {
|
||||
const printSettings = {
|
||||
...defaultPrintingSetting,
|
||||
requestID: getNextId()
|
||||
@@ -318,13 +333,20 @@ WebContents.prototype.printToPDF = function (options) {
|
||||
const error = new Error('height and width properties are required for pageSize');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
// Dimensions in Microns
|
||||
// 1 meter = 10^6 microns
|
||||
|
||||
// Dimensions in Microns - 1 meter = 10^6 microns
|
||||
const height = Math.ceil(pageSize.height);
|
||||
const width = Math.ceil(pageSize.width);
|
||||
if (!isValidCustomPageSize(width, height)) {
|
||||
const error = new Error('height and width properties must be minimum 352 microns.');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
printSettings.mediaSize = {
|
||||
name: 'CUSTOM',
|
||||
custom_display_name: 'Custom',
|
||||
height_microns: Math.ceil(pageSize.height),
|
||||
width_microns: Math.ceil(pageSize.width)
|
||||
height_microns: height,
|
||||
width_microns: width
|
||||
};
|
||||
} else if (PDFPageSizes[pageSize]) {
|
||||
printSettings.mediaSize = PDFPageSizes[pageSize];
|
||||
@@ -341,7 +363,12 @@ WebContents.prototype.printToPDF = function (options) {
|
||||
// PrinterType enum from //printing/print_job_constants.h
|
||||
printSettings.printerType = 2;
|
||||
if (this._printToPDF) {
|
||||
return this._printToPDF(printSettings);
|
||||
if (pendingPromise) {
|
||||
pendingPromise = pendingPromise.then(() => this._printToPDF(printSettings));
|
||||
} else {
|
||||
pendingPromise = this._printToPDF(printSettings);
|
||||
}
|
||||
return pendingPromise;
|
||||
} else {
|
||||
const error = new Error('Printing feature is disabled');
|
||||
return Promise.reject(error);
|
||||
@@ -359,12 +386,19 @@ WebContents.prototype.print = function (options = {}, callback) {
|
||||
if (!pageSize.height || !pageSize.width) {
|
||||
throw new Error('height and width properties are required for pageSize');
|
||||
}
|
||||
|
||||
// Dimensions in Microns - 1 meter = 10^6 microns
|
||||
const height = Math.ceil(pageSize.height);
|
||||
const width = Math.ceil(pageSize.width);
|
||||
if (!isValidCustomPageSize(width, height)) {
|
||||
throw new Error('height and width properties must be minimum 352 microns.');
|
||||
}
|
||||
|
||||
options.mediaSize = {
|
||||
name: 'CUSTOM',
|
||||
custom_display_name: 'Custom',
|
||||
height_microns: Math.ceil(pageSize.height),
|
||||
width_microns: Math.ceil(pageSize.width)
|
||||
height_microns: height,
|
||||
width_microns: width
|
||||
};
|
||||
} else if (PDFPageSizes[pageSize]) {
|
||||
options.mediaSize = PDFPageSizes[pageSize];
|
||||
@@ -411,8 +445,9 @@ WebContents.prototype.loadFile = function (filePath, options = {}) {
|
||||
};
|
||||
|
||||
const addReplyToEvent = (event) => {
|
||||
const { processId, frameId } = event;
|
||||
event.reply = (...args) => {
|
||||
event.sender.sendToFrame(event.frameId, ...args);
|
||||
event.sender.sendToFrame([processId, frameId], ...args);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -433,6 +468,10 @@ const addReturnValueToEvent = (event) => {
|
||||
});
|
||||
};
|
||||
|
||||
const loggingEnabled = () => {
|
||||
return process.env.ELECTRON_ENABLE_LOGGING || app.commandLine.hasSwitch('enable-logging');
|
||||
};
|
||||
|
||||
// Add JavaScript wrappers for WebContents class.
|
||||
WebContents.prototype._init = function () {
|
||||
// The navigation controller.
|
||||
@@ -501,8 +540,13 @@ WebContents.prototype._init = function () {
|
||||
app.emit('renderer-process-crashed', event, this, ...args);
|
||||
});
|
||||
|
||||
this.on('render-process-gone', (event, ...args) => {
|
||||
app.emit('render-process-gone', event, this, ...args);
|
||||
this.on('render-process-gone', (event, details) => {
|
||||
app.emit('render-process-gone', event, this, details);
|
||||
|
||||
// Log out a hint to help users better debug renderer crashes.
|
||||
if (loggingEnabled()) {
|
||||
console.info(`Renderer process ${details.reason} - see https://www.electronjs.org/docs/tutorial/application-debugging for potential debugging information.`);
|
||||
}
|
||||
});
|
||||
|
||||
// The devtools requests the webContents to reload.
|
||||
@@ -544,7 +588,6 @@ WebContents.prototype._init = function () {
|
||||
width: 800,
|
||||
height: 600,
|
||||
webContents,
|
||||
title: frameName,
|
||||
webPreferences,
|
||||
...options
|
||||
};
|
||||
@@ -562,6 +605,15 @@ WebContents.prototype._init = function () {
|
||||
app.emit('login', event, this, ...args);
|
||||
});
|
||||
|
||||
this.on('ready-to-show', () => {
|
||||
const owner = this.getOwnerBrowserWindow();
|
||||
if (owner && !owner.isDestroyed()) {
|
||||
process.nextTick(() => {
|
||||
owner.emit('ready-to-show');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const event = process.electronBinding('event').createEmpty();
|
||||
app.emit('web-contents-created', event, this);
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ export const getSourcesImpl = (event: Electron.IpcMainEvent | null, args: Electr
|
||||
}
|
||||
// Remove from currentlyRunning once we resolve or reject
|
||||
currentlyRunning = currentlyRunning.filter(running => running.options !== options);
|
||||
if (event) {
|
||||
event.sender.removeListener('destroyed', stopRunning);
|
||||
}
|
||||
};
|
||||
|
||||
capturer._onerror = (error: string) => {
|
||||
@@ -66,7 +69,7 @@ export const getSourcesImpl = (event: Electron.IpcMainEvent | null, args: Electr
|
||||
// reference to emit and the capturer itself so that it never dispatches
|
||||
// back to the renderer
|
||||
if (event) {
|
||||
event.sender.once('destroyed', () => stopRunning());
|
||||
event.sender.once('destroyed', stopRunning);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import * as fs from 'fs';
|
||||
import { Socket } from 'net';
|
||||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
|
||||
const Module = require('module');
|
||||
|
||||
// We modified the original process.argv to let node.js load the init.js,
|
||||
|
||||
@@ -4,12 +4,13 @@ import * as electron from 'electron';
|
||||
import { EventEmitter } from 'events';
|
||||
import objectsRegistry from './objects-registry';
|
||||
import { ipcMainInternal } from '../ipc-main-internal';
|
||||
import { isPromise, isSerializableObject } from '@electron/internal/common/type-utils';
|
||||
import { isPromise, isSerializableObject, deserialize, serialize } from '@electron/internal/common/type-utils';
|
||||
import { Size } from 'electron/main';
|
||||
|
||||
const v8Util = process.electronBinding('v8_util');
|
||||
const eventBinding = process.electronBinding('event');
|
||||
const features = process.electronBinding('features');
|
||||
const { NativeImage } = process.electronBinding('native_image');
|
||||
|
||||
if (!features.isRemoteModuleEnabled()) {
|
||||
throw new Error('remote module is disabled');
|
||||
@@ -114,6 +115,9 @@ type MetaType = {
|
||||
} | {
|
||||
type: 'promise',
|
||||
then: MetaType
|
||||
} | {
|
||||
type: 'nativeimage'
|
||||
value: electron.NativeImage
|
||||
}
|
||||
|
||||
// Convert a real value into meta data.
|
||||
@@ -124,6 +128,8 @@ const valueToMeta = function (sender: electron.WebContents, contextId: string, v
|
||||
// Recognize certain types of objects.
|
||||
if (value instanceof Buffer) {
|
||||
type = 'buffer';
|
||||
} else if (value instanceof NativeImage) {
|
||||
type = 'nativeimage';
|
||||
} else if (Array.isArray(value)) {
|
||||
type = 'array';
|
||||
} else if (value instanceof Error) {
|
||||
@@ -147,6 +153,8 @@ const valueToMeta = function (sender: electron.WebContents, contextId: string, v
|
||||
type,
|
||||
members: value.map((el: any) => valueToMeta(sender, contextId, el, optimizeSimpleObject))
|
||||
};
|
||||
} else if (type === 'nativeimage') {
|
||||
return { type, value: serialize(value) };
|
||||
} else if (type === 'object' || type === 'function') {
|
||||
return {
|
||||
type,
|
||||
@@ -234,7 +242,10 @@ type MetaTypeFromRenderer = {
|
||||
} | {
|
||||
type: 'object',
|
||||
name: string,
|
||||
members: { name: string, value: MetaTypeFromRenderer }[]
|
||||
members: {
|
||||
name: string,
|
||||
value: MetaTypeFromRenderer
|
||||
}[]
|
||||
} | {
|
||||
type: 'function-with-return-value',
|
||||
value: MetaTypeFromRenderer
|
||||
@@ -245,7 +256,12 @@ type MetaTypeFromRenderer = {
|
||||
length: number
|
||||
} | {
|
||||
type: 'nativeimage',
|
||||
value: { size: Size, buffer: Buffer, scaleFactor: number, dataURL: string }[]
|
||||
value: {
|
||||
size: Size,
|
||||
buffer: Buffer,
|
||||
scaleFactor: number,
|
||||
dataURL: string
|
||||
}[]
|
||||
}
|
||||
|
||||
const fakeConstructor = (constructor: Function, name: string) =>
|
||||
@@ -260,18 +276,11 @@ const fakeConstructor = (constructor: Function, name: string) =>
|
||||
});
|
||||
|
||||
// Convert array of meta data from renderer into array of real values.
|
||||
const unwrapArgs = function (sender: electron.WebContents, frameId: number, contextId: string, args: any[]) {
|
||||
const unwrapArgs = function (sender: electron.WebContents, frameId: [number, number], contextId: string, args: any[]) {
|
||||
const metaToValue = function (meta: MetaTypeFromRenderer): any {
|
||||
switch (meta.type) {
|
||||
case 'nativeimage': {
|
||||
const image = electron.nativeImage.createEmpty();
|
||||
for (const rep of meta.value) {
|
||||
const { size, scaleFactor, dataURL } = rep;
|
||||
const { width, height } = size;
|
||||
image.addRepresentation({ dataURL, scaleFactor, width, height });
|
||||
}
|
||||
return image;
|
||||
}
|
||||
case 'nativeimage':
|
||||
return deserialize(meta.value);
|
||||
case 'value':
|
||||
return meta.value;
|
||||
case 'remote-object':
|
||||
@@ -322,7 +331,7 @@ const unwrapArgs = function (sender: electron.WebContents, frameId: number, cont
|
||||
v8Util.setHiddenValue(callIntoRenderer, 'location', meta.location);
|
||||
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length });
|
||||
|
||||
v8Util.setRemoteCallbackFreer(callIntoRenderer, frameId, contextId, meta.id, sender);
|
||||
v8Util.setRemoteCallbackFreer(callIntoRenderer, frameId[0], frameId[1], contextId, meta.id, sender);
|
||||
rendererFunctions.set(objectId, callIntoRenderer);
|
||||
return callIntoRenderer;
|
||||
}
|
||||
@@ -471,7 +480,7 @@ handleRemoteCommand('ELECTRON_BROWSER_CURRENT_WEB_CONTENTS', function (event, co
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_CONSTRUCTOR', function (event, contextId, id, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const constructor = objectsRegistry.get(id);
|
||||
|
||||
if (constructor == null) {
|
||||
@@ -482,7 +491,7 @@ handleRemoteCommand('ELECTRON_BROWSER_CONSTRUCTOR', function (event, contextId,
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_FUNCTION_CALL', function (event, contextId, id, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const func = objectsRegistry.get(id);
|
||||
|
||||
if (func == null) {
|
||||
@@ -499,7 +508,7 @@ handleRemoteCommand('ELECTRON_BROWSER_FUNCTION_CALL', function (event, contextId
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', function (event, contextId, id, method, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const object = objectsRegistry.get(id);
|
||||
|
||||
if (object == null) {
|
||||
@@ -510,7 +519,7 @@ handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', function (event, cont
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CALL', function (event, contextId, id, method, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const object = objectsRegistry.get(id);
|
||||
|
||||
if (object == null) {
|
||||
@@ -527,7 +536,7 @@ handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CALL', function (event, contextId,
|
||||
});
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_MEMBER_SET', function (event, contextId, id, name, args) {
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args);
|
||||
args = unwrapArgs(event.sender, [event.processId, event.frameId], contextId, args);
|
||||
const obj = objectsRegistry.get(id);
|
||||
|
||||
if (obj == null) {
|
||||
|
||||
@@ -83,7 +83,7 @@ const getPreloadScript = async function (preloadPath) {
|
||||
let preloadSrc = null;
|
||||
let preloadError = null;
|
||||
try {
|
||||
preloadSrc = (await fs.promises.readFile(preloadPath)).toString();
|
||||
preloadSrc = await fs.promises.readFile(preloadPath, 'utf8');
|
||||
} catch (error) {
|
||||
preloadError = error;
|
||||
}
|
||||
@@ -134,3 +134,7 @@ ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_SET_UPLOAD_TO_SERVER', (event,
|
||||
ipcMainUtils.handleSync('ELECTRON_CRASH_REPORTER_GET_CRASHES_DIRECTORY', () => {
|
||||
return electron.crashReporter.getCrashesDirectory();
|
||||
});
|
||||
|
||||
ipcMainInternal.handle('ELECTRON_NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH', async (_, path, size) => {
|
||||
return typeUtils.serialize(await electron.nativeImage.createThumbnailFromPath(path, size));
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user