mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
330 Commits
v7.1.10
...
v8.0.0-nig
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c250cd6e7c | ||
|
|
f80a17c5be | ||
|
|
5e11be6898 | ||
|
|
ebd55c1147 | ||
|
|
2ce90f8806 | ||
|
|
b3e7657159 | ||
|
|
23066f8cce | ||
|
|
de3c1fae7f | ||
|
|
94ec4ecabe | ||
|
|
c16a186de0 | ||
|
|
8da9a3c416 | ||
|
|
8d9ba87e05 | ||
|
|
c85648a8a1 | ||
|
|
0c87471c12 | ||
|
|
f3cf2566c1 | ||
|
|
9b534e9aab | ||
|
|
3f72f07a7f | ||
|
|
e26fa9090d | ||
|
|
39d19d23d1 | ||
|
|
0a09f27735 | ||
|
|
8dae38639a | ||
|
|
87bd0501c4 | ||
|
|
ccff140046 | ||
|
|
e1eb9519f5 | ||
|
|
ad34d7fc32 | ||
|
|
4945a9fce9 | ||
|
|
7f320eef0e | ||
|
|
513c8536c0 | ||
|
|
82ff142f9c | ||
|
|
509587eb81 | ||
|
|
80af35e0cd | ||
|
|
f054d5862c | ||
|
|
8a2ba597bb | ||
|
|
e543fe702c | ||
|
|
2470ef2e91 | ||
|
|
fe956f87ec | ||
|
|
1c0a21a8bc | ||
|
|
2f03d393c3 | ||
|
|
712d77dc8b | ||
|
|
bf978e09e4 | ||
|
|
4ac4b34ae9 | ||
|
|
01ed55ff02 | ||
|
|
ef690c035d | ||
|
|
969b4d1dd3 | ||
|
|
a9e695d05f | ||
|
|
b7b0992768 | ||
|
|
d3922f95e6 | ||
|
|
9457c796b1 | ||
|
|
37e34395de | ||
|
|
4f815d8469 | ||
|
|
e099edc2c2 | ||
|
|
5e942cea8d | ||
|
|
ead8f2bbcd | ||
|
|
efe6e7b04d | ||
|
|
cc0312567e | ||
|
|
593f1774e9 | ||
|
|
0653e31767 | ||
|
|
b18fb96ecf | ||
|
|
26d9ef9403 | ||
|
|
c32bea5ae0 | ||
|
|
7f0ec3091e | ||
|
|
597a8b5ec7 | ||
|
|
c25f0a1779 | ||
|
|
bac15ef86f | ||
|
|
297b81fa1d | ||
|
|
913ec1e0d0 | ||
|
|
d090b0cd2d | ||
|
|
1e0b87732f | ||
|
|
9abdfc11a9 | ||
|
|
ae6f08d56e | ||
|
|
26014d19e1 | ||
|
|
e83c299454 | ||
|
|
b136819371 | ||
|
|
c46a386970 | ||
|
|
6f2fe7560a | ||
|
|
e459114149 | ||
|
|
624ba4f642 | ||
|
|
63f08fcdb0 | ||
|
|
3f5833ce5d | ||
|
|
ffe2182883 | ||
|
|
e510af77b2 | ||
|
|
afc59aefb7 | ||
|
|
b0fe3e20e6 | ||
|
|
eb2d2264d0 | ||
|
|
104088b86b | ||
|
|
11cd0db86b | ||
|
|
8bf74164e2 | ||
|
|
eaa18041e1 | ||
|
|
d2a94e6b13 | ||
|
|
42999f42f2 | ||
|
|
dfd2135647 | ||
|
|
7c45c2fdef | ||
|
|
2cac40444b | ||
|
|
f566e562a3 | ||
|
|
0e61709fa7 | ||
|
|
2b316f3843 | ||
|
|
660e566201 | ||
|
|
999f7df158 | ||
|
|
816bc5c8a7 | ||
|
|
99f1b96c4f | ||
|
|
334ea36f38 | ||
|
|
c485c1e4b0 | ||
|
|
b2652beceb | ||
|
|
3ec17a88ba | ||
|
|
5dee8a5717 | ||
|
|
ace0284eef | ||
|
|
5ccc043d86 | ||
|
|
fd31a99ef0 | ||
|
|
ff1f224d96 | ||
|
|
0b26d7a0e2 | ||
|
|
5f59c6ddfe | ||
|
|
a9f2a52ce0 | ||
|
|
d84e2e3972 | ||
|
|
49bd74ff0e | ||
|
|
d395799917 | ||
|
|
6e9a23a884 | ||
|
|
0979fb7eee | ||
|
|
9ab06af786 | ||
|
|
6087f89aac | ||
|
|
432ae81823 | ||
|
|
2c23e44ed9 | ||
|
|
7be1905023 | ||
|
|
20e3c519dd | ||
|
|
8a0a41b9ef | ||
|
|
93da8e2b3d | ||
|
|
196fceabdb | ||
|
|
0d16be9560 | ||
|
|
137622931b | ||
|
|
cd096289e9 | ||
|
|
88e32ef231 | ||
|
|
bff16e027a | ||
|
|
a453f2ae6c | ||
|
|
8b523cf88a | ||
|
|
65ebb6e547 | ||
|
|
c29e4b096d | ||
|
|
8cdfd30ba5 | ||
|
|
81ae154714 | ||
|
|
504cdb13f0 | ||
|
|
b601f3a031 | ||
|
|
96b42bddb8 | ||
|
|
cc9436f288 | ||
|
|
bedc5f7da9 | ||
|
|
96c3fec855 | ||
|
|
cad73732c0 | ||
|
|
39475f9404 | ||
|
|
8589ab27a4 | ||
|
|
f537366387 | ||
|
|
d7161742d2 | ||
|
|
6e88b6b445 | ||
|
|
614079654c | ||
|
|
51015c5b48 | ||
|
|
c621a36320 | ||
|
|
e37ad09330 | ||
|
|
bfe256891c | ||
|
|
0f5ff1f5bb | ||
|
|
e96a042223 | ||
|
|
5cbbd489d5 | ||
|
|
805a55099b | ||
|
|
654338693f | ||
|
|
a9e3dabc8a | ||
|
|
609403fba6 | ||
|
|
6b55584923 | ||
|
|
81e6f317c9 | ||
|
|
7d4e0ad7b0 | ||
|
|
35ebbb5f6e | ||
|
|
c819fbe852 | ||
|
|
c03288f458 | ||
|
|
90d62e5b98 | ||
|
|
b3947d6a83 | ||
|
|
eed72c35d7 | ||
|
|
79e936aea8 | ||
|
|
01fdb80f7c | ||
|
|
04debd5890 | ||
|
|
af138dab55 | ||
|
|
f212ed85dd | ||
|
|
99de0975c3 | ||
|
|
41d8247ffc | ||
|
|
217ed9aabc | ||
|
|
538c4763cf | ||
|
|
3bc5302d78 | ||
|
|
987300c97a | ||
|
|
27ce6a9cd3 | ||
|
|
832c926712 | ||
|
|
ae9424d93a | ||
|
|
1dcda7b809 | ||
|
|
bdc84d0bfb | ||
|
|
4b8e1588b4 | ||
|
|
4eee71ffbf | ||
|
|
bdb20d53cb | ||
|
|
7e61cd0dfb | ||
|
|
2542c51c48 | ||
|
|
92c3a4e4c2 | ||
|
|
4e809f0048 | ||
|
|
d04072d1eb | ||
|
|
cddbddc543 | ||
|
|
c57db7f163 | ||
|
|
94c6b256de | ||
|
|
f6c523db13 | ||
|
|
080fdb3817 | ||
|
|
181f663cf1 | ||
|
|
1eda92859f | ||
|
|
f54bc1cb2e | ||
|
|
b7d25ccb77 | ||
|
|
c89debd19a | ||
|
|
ef6d4a46c2 | ||
|
|
81e9dab52f | ||
|
|
698120daf0 | ||
|
|
c61020e9d3 | ||
|
|
6144408f3a | ||
|
|
7825d043f2 | ||
|
|
c6a8b7f959 | ||
|
|
6a3922d330 | ||
|
|
f7e3e1f97a | ||
|
|
ab0bf6d238 | ||
|
|
6667969887 | ||
|
|
12b00ca942 | ||
|
|
1f43af5cea | ||
|
|
268094e0ef | ||
|
|
9ccd6aa0dd | ||
|
|
46b6bcd99b | ||
|
|
4bc7b3b1a4 | ||
|
|
5e525b3e0f | ||
|
|
612e3f7ff7 | ||
|
|
991a56135d | ||
|
|
3bd829aee0 | ||
|
|
674779899e | ||
|
|
3f49f984e6 | ||
|
|
b7defaaf6a | ||
|
|
f10f44acf5 | ||
|
|
d258797d05 | ||
|
|
fb214a599e | ||
|
|
a4c0f26f06 | ||
|
|
145b4fae94 | ||
|
|
cd1b15a155 | ||
|
|
1dc02e6dbc | ||
|
|
0851697cb7 | ||
|
|
bd11be98aa | ||
|
|
a54d438e18 | ||
|
|
b33558d822 | ||
|
|
43e6d7fe88 | ||
|
|
8f1c51eaea | ||
|
|
090786b037 | ||
|
|
dba3927b4e | ||
|
|
56d10aeef7 | ||
|
|
6a76540cb6 | ||
|
|
2c002a3342 | ||
|
|
42ac64284f | ||
|
|
2595cb5698 | ||
|
|
c3bb73a711 | ||
|
|
e59095423e | ||
|
|
db21391156 | ||
|
|
12df0e8994 | ||
|
|
ca0cf5415e | ||
|
|
33f2ec6355 | ||
|
|
680399f476 | ||
|
|
d0c7a91a50 | ||
|
|
27b2747b61 | ||
|
|
9b1f698770 | ||
|
|
efa1818cb4 | ||
|
|
246187a20f | ||
|
|
4c54cfc692 | ||
|
|
5d892a557f | ||
|
|
49fe2604b3 | ||
|
|
28466a39d8 | ||
|
|
e1824c00a9 | ||
|
|
b5798326e8 | ||
|
|
fee84de782 | ||
|
|
e8fa248571 | ||
|
|
ba5ee79af8 | ||
|
|
69eac0d9d2 | ||
|
|
9713fa09e7 | ||
|
|
f654da9f56 | ||
|
|
ef03c4b7bb | ||
|
|
13df748f02 | ||
|
|
04dbd5c53f | ||
|
|
398c5d553d | ||
|
|
39f0bd3e82 | ||
|
|
2dffc9f6eb | ||
|
|
bc0a2d1b28 | ||
|
|
1749af9707 | ||
|
|
57507ca37c | ||
|
|
7861e9f728 | ||
|
|
84cbc1d6c0 | ||
|
|
03debb4ef9 | ||
|
|
ed3b69ffb1 | ||
|
|
0fb3c8cb7c | ||
|
|
58840f39bb | ||
|
|
da29ce355f | ||
|
|
7a9e6659f0 | ||
|
|
9eb89b4ac7 | ||
|
|
fec54c9c5d | ||
|
|
67169a5d0c | ||
|
|
eebea63bed | ||
|
|
9c7a216814 | ||
|
|
a8861e6a66 | ||
|
|
8a9a5d69b6 | ||
|
|
761a4deab3 | ||
|
|
50cc54e50b | ||
|
|
da2401ff39 | ||
|
|
c3d0fed9ed | ||
|
|
c0982d7316 | ||
|
|
f0396c19be | ||
|
|
33a9d898a6 | ||
|
|
cfd230d7f1 | ||
|
|
ee674acca4 | ||
|
|
8f043bbdaa | ||
|
|
750005f02b | ||
|
|
0bb227f8a4 | ||
|
|
40d9f828d4 | ||
|
|
49f2071e22 | ||
|
|
f08be2162a | ||
|
|
45e452557b | ||
|
|
df94cc1b13 | ||
|
|
bd28b876a0 | ||
|
|
e959137a4b | ||
|
|
d0800aa200 | ||
|
|
3011a0f14f | ||
|
|
ee64c6ab86 | ||
|
|
79277cc383 | ||
|
|
e78b902a7d | ||
|
|
e8c4e6f0b3 | ||
|
|
2e785899dd | ||
|
|
115b57649e | ||
|
|
b80429ab7f | ||
|
|
c190e64012 | ||
|
|
3a6cafaf0a | ||
|
|
c76b0b70c1 | ||
|
|
c71cdce0b7 | ||
|
|
a5f87cee6b | ||
|
|
bf66fe51f6 |
@@ -1,3 +1,46 @@
|
||||
version: 2.1
|
||||
|
||||
parameters:
|
||||
upload-to-s3:
|
||||
type: string
|
||||
default: '1'
|
||||
|
||||
run-lint:
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
run-build-linux:
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
run-build-mac:
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
run-linux-x64-publish:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
run-linux-ia32-publish:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
run-linux-arm-publish:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
run-linux-arm64-publish:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
run-osx-publish:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
run-mas-publish:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "SLACK_WEBHOOK" Slack hook URL to send notifications.
|
||||
#
|
||||
@@ -32,6 +75,7 @@ machine-mac-large: &machine-mac-large
|
||||
# Build configurations options.
|
||||
env-debug-build: &env-debug-build
|
||||
GN_CONFIG: //electron/build/args/debug.gn
|
||||
SKIP_DIST_ZIP: '1'
|
||||
|
||||
env-testing-build: &env-testing-build
|
||||
GN_CONFIG: //electron/build/args/testing.gn
|
||||
@@ -41,7 +85,6 @@ env-release-build: &env-release-build
|
||||
GN_CONFIG: //electron/build/args/release.gn
|
||||
STRIP_BINARIES: true
|
||||
GENERATE_SYMBOLS: true
|
||||
CHECK_DIST_MANIFEST: '1'
|
||||
|
||||
env-headless-testing: &env-headless-testing
|
||||
DISPLAY: ':99.0'
|
||||
@@ -93,7 +136,7 @@ env-linux-medium: &env-linux-medium
|
||||
|
||||
env-linux-2xlarge: &env-linux-2xlarge
|
||||
NUMBER_OF_NINJA_PROCESSES: 34
|
||||
|
||||
|
||||
env-linux-2xlarge-release: &env-linux-2xlarge-release
|
||||
NUMBER_OF_NINJA_PROCESSES: 16
|
||||
|
||||
@@ -106,9 +149,6 @@ env-mac-large: &env-mac-large
|
||||
env-mac-large-release: &env-mac-large-release
|
||||
NUMBER_OF_NINJA_PROCESSES: 8
|
||||
|
||||
env-disable-crash-reporter-tests: &env-disable-crash-reporter-tests
|
||||
DISABLE_CRASH_REPORTER_TESTS: true
|
||||
|
||||
env-ninja-status: &env-ninja-status
|
||||
NINJA_STATUS: "[%r processes, %f/%t @ %o/s : %es] "
|
||||
|
||||
@@ -288,22 +328,21 @@ step-electron-build: &step-electron-build
|
||||
cd src
|
||||
ninja -C out/Default electron -j $NUMBER_OF_NINJA_PROCESSES
|
||||
|
||||
step-native-unittests-build: &step-native-unittests-build
|
||||
run:
|
||||
name: Build native test targets
|
||||
no_output_timeout: 30m
|
||||
command: |
|
||||
cd src
|
||||
ninja -C out/Default shell_browser_ui_unittests -j $NUMBER_OF_NINJA_PROCESSES
|
||||
|
||||
step-maybe-electron-dist-strip: &step-maybe-electron-dist-strip
|
||||
run:
|
||||
name: Strip electron binaries
|
||||
command: |
|
||||
if [ "$STRIP_BINARIES" == "true" ] && [ "`uname`" == "Linux" ]; then
|
||||
if [ x"$TARGET_ARCH" == x ]; then
|
||||
target_cpu=x64
|
||||
elif [ "$TARGET_ARCH" == "ia32" ]; then
|
||||
target_cpu=x86
|
||||
else
|
||||
target_cpu="$TARGET_ARCH"
|
||||
fi
|
||||
if [ "$STRIP_BINARIES" == "true" ] && [ "`uname`" != "Darwin" ]; then
|
||||
cd src
|
||||
electron/script/copy-debug-symbols.py --target-cpu="$target_cpu" --out-dir=out/Default/debug --compress
|
||||
electron/script/strip-binaries.py --target-cpu="$target_cpu"
|
||||
electron/script/add-debug-link.py --target-cpu="$target_cpu" --debug-dir=out/Default/debug
|
||||
electron/script/strip-binaries.py --target-cpu="$TARGET_ARCH"
|
||||
fi
|
||||
|
||||
step-electron-dist-build: &step-electron-dist-build
|
||||
@@ -311,28 +350,30 @@ step-electron-dist-build: &step-electron-dist-build
|
||||
name: Build dist.zip
|
||||
command: |
|
||||
cd src
|
||||
ninja -C out/Default electron:electron_dist_zip
|
||||
if [ "$CHECK_DIST_MANIFEST" == "1" ]; then
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
target_os=mac
|
||||
target_cpu=x64
|
||||
if [ x"$MAS_BUILD" == x"true" ]; then
|
||||
target_os=mac_mas
|
||||
fi
|
||||
elif [ "`uname`" == "Linux" ]; then
|
||||
target_os=linux
|
||||
if [ x"$TARGET_ARCH" == x ]; then
|
||||
if [ "$SKIP_DIST_ZIP" != "1" ]; then
|
||||
ninja -C out/Default electron:electron_dist_zip
|
||||
if [ "$CHECK_DIST_MANIFEST" == "1" ]; then
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
target_os=mac
|
||||
target_cpu=x64
|
||||
elif [ "$TARGET_ARCH" == "ia32" ]; then
|
||||
target_cpu=x86
|
||||
if [ x"$MAS_BUILD" == x"true" ]; then
|
||||
target_os=mac_mas
|
||||
fi
|
||||
elif [ "`uname`" == "Linux" ]; then
|
||||
target_os=linux
|
||||
if [ x"$TARGET_ARCH" == x ]; then
|
||||
target_cpu=x64
|
||||
elif [ "$TARGET_ARCH" == "ia32" ]; then
|
||||
target_cpu=x86
|
||||
else
|
||||
target_cpu="$TARGET_ARCH"
|
||||
fi
|
||||
else
|
||||
target_cpu="$TARGET_ARCH"
|
||||
echo "Unknown system: `uname`"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Unknown system: `uname`"
|
||||
exit 1
|
||||
electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.$target_os.$target_cpu.manifest
|
||||
fi
|
||||
electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.$target_os.$target_cpu.manifest
|
||||
fi
|
||||
|
||||
step-electron-dist-store: &step-electron-dist-store
|
||||
@@ -366,6 +407,11 @@ step-nodejs-headers-store: &step-nodejs-headers-store
|
||||
path: src/out/Default/gen/node_headers.tar.gz
|
||||
destination: node_headers.tar.gz
|
||||
|
||||
step-native-unittests-store: &step-native-unittests-store
|
||||
store_artifacts:
|
||||
path: src/out/Default/shell_browser_ui_unittests
|
||||
destination: shell_browser_ui_unittests
|
||||
|
||||
step-electron-publish: &step-electron-publish
|
||||
run:
|
||||
name: Publish Electron Dist
|
||||
@@ -386,8 +432,12 @@ step-persist-data-for-tests: &step-persist-data-for-tests
|
||||
# Build artifacts
|
||||
- src/out/Default/dist.zip
|
||||
- src/out/Default/mksnapshot.zip
|
||||
- src/out/Default/shell_browser_ui_unittests
|
||||
- src/out/Default/gen/node_headers
|
||||
- src/out/ffmpeg/ffmpeg.zip
|
||||
- src/electron
|
||||
- src/third_party/electron_node
|
||||
- src/third_party/nan
|
||||
|
||||
step-electron-dist-unzip: &step-electron-dist-unzip
|
||||
run:
|
||||
@@ -475,7 +525,9 @@ step-mksnapshot-build: &step-mksnapshot-build
|
||||
electron/script/strip-binaries.py --file $PWD/out/Default/mksnapshot
|
||||
fi
|
||||
fi
|
||||
ninja -C out/Default electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
if [ "$SKIP_DIST_ZIP" != "1" ]; then
|
||||
ninja -C out/Default electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
fi
|
||||
|
||||
step-mksnapshot-store: &step-mksnapshot-store
|
||||
store_artifacts:
|
||||
@@ -497,6 +549,8 @@ step-maybe-zip-symbols: &step-maybe-zip-symbols
|
||||
command: |
|
||||
cd src
|
||||
export BUILD_PATH="$PWD/out/Default"
|
||||
ninja -C out/Default electron:licenses
|
||||
ninja -C out/Default electron:electron_version
|
||||
electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
|
||||
step-maybe-cross-arch-snapshot: &step-maybe-cross-arch-snapshot
|
||||
@@ -661,7 +715,7 @@ steps-lint: &steps-lint
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
gn_version="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)"
|
||||
|
||||
cipd ensure -ensure-file - -root . <<-CIPD
|
||||
cipd ensure -ensure-file - -root . \<<-CIPD
|
||||
\$ServiceURL https://chrome-infra-packages.appspot.com/
|
||||
@Subdir src/buildtools/linux64
|
||||
gn/gn/linux-amd64 $gn_version
|
||||
@@ -765,24 +819,78 @@ steps-electron-build: &steps-electron-build
|
||||
at: .
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-setup-env-for-build
|
||||
- *step-restore-brew-cache
|
||||
- *step-get-more-space-on-mac
|
||||
- *step-install-npm-deps-on-mac
|
||||
- *step-fix-sync-on-mac
|
||||
- *step-gn-gen-default
|
||||
- *step-delete-git-directories
|
||||
|
||||
# Electron app
|
||||
- *step-electron-build
|
||||
- *step-maybe-electron-dist-strip
|
||||
- *step-electron-dist-build
|
||||
- *step-electron-dist-store
|
||||
- *step-ninja-summary
|
||||
|
||||
# Native test targets
|
||||
- *step-native-unittests-build
|
||||
- *step-native-unittests-store
|
||||
|
||||
# Node.js headers
|
||||
- *step-nodejs-headers-build
|
||||
- *step-nodejs-headers-store
|
||||
|
||||
- *step-show-sccache-stats
|
||||
|
||||
steps-electron-build-for-tests: &steps-electron-build-for-tests
|
||||
# mksnapshot
|
||||
- *step-mksnapshot-build
|
||||
- *step-mksnapshot-store
|
||||
- *step-maybe-cross-arch-snapshot
|
||||
- *step-maybe-cross-arch-snapshot-store
|
||||
|
||||
# ffmpeg
|
||||
- *step-ffmpeg-gn-gen
|
||||
- *step-ffmpeg-build
|
||||
- *step-ffmpeg-store
|
||||
|
||||
# Save all data needed for a further tests run.
|
||||
- *step-persist-data-for-tests
|
||||
|
||||
- *step-maybe-generate-breakpad-symbols
|
||||
- *step-maybe-zip-symbols
|
||||
|
||||
# Trigger tests on arm hardware if needed
|
||||
- *step-maybe-trigger-arm-test
|
||||
|
||||
- *step-maybe-notify-slack-failure
|
||||
|
||||
steps-electron-build-with-inline-checkout-for-tests: &steps-electron-build-with-inline-checkout-for-tests
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
# Checkout - Copied ffrom steps-checkout
|
||||
- *step-checkout-electron
|
||||
- *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-generate-deps-hash
|
||||
- *step-touch-sync-done
|
||||
- *step-maybe-restore-src-cache
|
||||
- *step-maybe-restore-git-cache
|
||||
- *step-set-git-cache-path
|
||||
# This sync call only runs if .circle-sync-done is an EMPTY file
|
||||
- *step-gclient-sync
|
||||
# These next few steps reset Electron to the correct commit regardless of which cache was restored
|
||||
- run:
|
||||
name: Wipe Electron
|
||||
command: rm -rf src/electron
|
||||
- *step-checkout-electron
|
||||
- *step-run-electron-only-hooks
|
||||
- *step-generate-deps-hash-cleanly
|
||||
- *step-mark-sync-done
|
||||
- *step-minimize-workspace-size-from-checkout
|
||||
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-setup-env-for-build
|
||||
- *step-restore-brew-cache
|
||||
@@ -799,6 +907,10 @@ steps-electron-build-for-tests: &steps-electron-build-for-tests
|
||||
- *step-electron-dist-store
|
||||
- *step-ninja-summary
|
||||
|
||||
# Native test targets
|
||||
- *step-native-unittests-build
|
||||
- *step-native-unittests-store
|
||||
|
||||
# Node.js headers
|
||||
- *step-nodejs-headers-build
|
||||
- *step-nodejs-headers-store
|
||||
@@ -1018,7 +1130,6 @@ chromium-upgrade-branches: &chromium-upgrade-branches
|
||||
/chromium\-upgrade\/[0-9]+/
|
||||
|
||||
# List of all jobs.
|
||||
version: 2
|
||||
jobs:
|
||||
# Layer 0: Lint. Standalone.
|
||||
lint:
|
||||
@@ -1078,7 +1189,8 @@ jobs:
|
||||
<<: *env-debug-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-electron-build-with-inline-checkout-for-tests
|
||||
|
||||
linux-x64-debug-gn-check:
|
||||
<<: *machine-linux-medium
|
||||
@@ -1094,7 +1206,8 @@ jobs:
|
||||
<<: *env-testing-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build-for-tests
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-electron-build-with-inline-checkout-for-tests
|
||||
|
||||
linux-x64-testing-no-run-as-node:
|
||||
<<: *machine-linux-2xlarge
|
||||
@@ -1104,7 +1217,8 @@ jobs:
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *env-disable-run-as-node
|
||||
<<: *steps-electron-build-for-tests
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-electron-build-with-inline-checkout-for-tests
|
||||
|
||||
linux-x64-testing-gn-check:
|
||||
<<: *machine-linux-medium
|
||||
@@ -1125,12 +1239,12 @@ jobs:
|
||||
linux-x64-release:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
<<: *env-linux-2xlarge
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build-for-tests
|
||||
<<: *steps-electron-build
|
||||
|
||||
linux-x64-publish:
|
||||
<<: *machine-linux-2xlarge
|
||||
@@ -1138,6 +1252,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 >>
|
||||
<<: *steps-electron-build-for-publish
|
||||
|
||||
linux-ia32-debug:
|
||||
@@ -1148,7 +1264,8 @@ jobs:
|
||||
<<: *env-debug-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-electron-build-with-inline-checkout-for-tests
|
||||
|
||||
linux-ia32-testing:
|
||||
<<: *machine-linux-2xlarge
|
||||
@@ -1158,7 +1275,8 @@ jobs:
|
||||
<<: *env-testing-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build-for-tests
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-electron-build-with-inline-checkout-for-tests
|
||||
|
||||
linux-ia32-chromedriver:
|
||||
<<: *machine-linux-medium
|
||||
@@ -1173,13 +1291,13 @@ jobs:
|
||||
linux-ia32-release:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
<<: *env-linux-2xlarge
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-ia32
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build-for-tests
|
||||
<<: *steps-electron-build
|
||||
|
||||
linux-ia32-publish:
|
||||
<<: *machine-linux-2xlarge
|
||||
@@ -1188,6 +1306,8 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
|
||||
<<: *env-ia32
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
|
||||
<<: *steps-electron-build-for-publish
|
||||
|
||||
linux-arm-debug:
|
||||
@@ -1198,7 +1318,8 @@ jobs:
|
||||
<<: *env-debug-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-electron-build-with-inline-checkout-for-tests
|
||||
|
||||
linux-arm-testing:
|
||||
<<: *machine-linux-2xlarge
|
||||
@@ -1209,7 +1330,8 @@ jobs:
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
TRIGGER_ARM_TEST: true
|
||||
<<: *steps-electron-build-for-tests
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-electron-build-with-inline-checkout-for-tests
|
||||
|
||||
linux-arm-chromedriver:
|
||||
<<: *machine-linux-medium
|
||||
@@ -1224,13 +1346,13 @@ jobs:
|
||||
linux-arm-release:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
<<: *env-linux-2xlarge
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-arm
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build-for-tests
|
||||
<<: *steps-electron-build
|
||||
|
||||
linux-arm-publish:
|
||||
<<: *machine-linux-2xlarge
|
||||
@@ -1238,7 +1360,9 @@ jobs:
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-arm
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
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 >>
|
||||
<<: *steps-electron-build-for-publish
|
||||
|
||||
linux-arm64-debug:
|
||||
@@ -1249,7 +1373,8 @@ jobs:
|
||||
<<: *env-debug-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-electron-build-with-inline-checkout-for-tests
|
||||
|
||||
linux-arm64-debug-gn-check:
|
||||
<<: *machine-linux-medium
|
||||
@@ -1268,7 +1393,8 @@ jobs:
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
TRIGGER_ARM_TEST: true
|
||||
<<: *steps-electron-build-for-tests
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-electron-build-with-inline-checkout-for-tests
|
||||
|
||||
linux-arm64-testing-gn-check:
|
||||
<<: *machine-linux-medium
|
||||
@@ -1291,13 +1417,13 @@ jobs:
|
||||
linux-arm64-release:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
<<: *env-linux-2xlarge
|
||||
<<: *env-linux-2xlarge-release
|
||||
<<: *env-arm64
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build-for-tests
|
||||
<<: *steps-electron-build
|
||||
|
||||
linux-arm64-publish:
|
||||
<<: *machine-linux-2xlarge
|
||||
@@ -1305,7 +1431,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 >>
|
||||
<<: *steps-electron-build-for-publish
|
||||
|
||||
osx-testing:
|
||||
@@ -1315,7 +1443,7 @@ jobs:
|
||||
<<: *env-testing-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build-for-tests
|
||||
<<: *steps-electron-build
|
||||
|
||||
osx-debug:
|
||||
<<: *machine-mac-large
|
||||
@@ -1324,7 +1452,7 @@ jobs:
|
||||
<<: *env-debug-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build-for-tests
|
||||
<<: *steps-electron-build
|
||||
|
||||
osx-debug-gn-check:
|
||||
<<: *machine-mac
|
||||
@@ -1356,14 +1484,16 @@ jobs:
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build-for-tests
|
||||
<<: *steps-electron-build
|
||||
|
||||
osx-publish:
|
||||
<<: *machine-mac-large
|
||||
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 >>
|
||||
<<: *steps-electron-build-for-publish
|
||||
|
||||
mas-testing:
|
||||
@@ -1374,7 +1504,7 @@ jobs:
|
||||
<<: *env-testing-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build-for-tests
|
||||
<<: *steps-electron-build
|
||||
|
||||
mas-debug:
|
||||
<<: *machine-mac-large
|
||||
@@ -1384,7 +1514,7 @@ jobs:
|
||||
<<: *env-debug-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build-for-tests
|
||||
<<: *steps-electron-build
|
||||
|
||||
mas-debug-gn-check:
|
||||
<<: *machine-mac
|
||||
@@ -1418,8 +1548,8 @@ jobs:
|
||||
<<: *env-mas
|
||||
<<: *env-release-build
|
||||
<<: *env-enable-sccache
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build-for-tests
|
||||
<<: *env-ninja-status
|
||||
<<: *steps-electron-build
|
||||
|
||||
mas-publish:
|
||||
<<: *machine-mac-large
|
||||
@@ -1427,7 +1557,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 >>
|
||||
<<: *steps-electron-build-for-publish
|
||||
|
||||
# Layer 3: Tests.
|
||||
@@ -1577,7 +1709,6 @@ jobs:
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
<<: *env-disable-crash-reporter-tests
|
||||
<<: *steps-tests
|
||||
|
||||
osx-release-tests:
|
||||
@@ -1586,7 +1717,6 @@ jobs:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *env-disable-crash-reporter-tests
|
||||
<<: *steps-tests
|
||||
|
||||
osx-verify-ffmpeg:
|
||||
@@ -1682,28 +1812,67 @@ jobs:
|
||||
- *step-maybe-notify-slack-success
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
version: 2.1
|
||||
|
||||
# The publish workflows below each contain one job so that they are
|
||||
# compatible with how sudowoodo works today. If these workflows are
|
||||
# changed to have multiple jobs, then scripts/release/ci-release-build.js
|
||||
# will need to be updated and there will most likely need to be changes to
|
||||
# sudowoodo
|
||||
|
||||
publish-x64-linux:
|
||||
when: << pipeline.parameters.run-linux-x64-publish >>
|
||||
jobs:
|
||||
- linux-x64-publish:
|
||||
context: release-env
|
||||
|
||||
publish-ia32-linux:
|
||||
when: << pipeline.parameters.run-linux-ia32-publish >>
|
||||
jobs:
|
||||
- linux-ia32-publish:
|
||||
context: release-env
|
||||
|
||||
publish-arm-linux:
|
||||
when: << pipeline.parameters.run-linux-arm-publish >>
|
||||
jobs:
|
||||
- linux-arm-publish:
|
||||
context: release-env
|
||||
|
||||
publish-arm64-linux:
|
||||
when: << pipeline.parameters.run-linux-arm64-publish >>
|
||||
jobs:
|
||||
- linux-arm64-publish:
|
||||
context: release-env
|
||||
|
||||
publish-osx:
|
||||
when: << pipeline.parameters.run-osx-publish >>
|
||||
jobs:
|
||||
- osx-publish:
|
||||
context: release-env
|
||||
|
||||
publish-mas:
|
||||
when: << pipeline.parameters.run-mas-publish >>
|
||||
jobs:
|
||||
- mas-publish:
|
||||
context: release-env
|
||||
|
||||
lint:
|
||||
when: << pipeline.parameters.run-lint >>
|
||||
jobs:
|
||||
- lint
|
||||
|
||||
build-linux:
|
||||
when: << pipeline.parameters.run-build-linux >>
|
||||
jobs:
|
||||
- linux-checkout-fast
|
||||
- linux-checkout-and-save-cache
|
||||
|
||||
- linux-x64-debug:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
- linux-x64-debug
|
||||
- linux-x64-debug-gn-check:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
- linux-x64-testing:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
- linux-x64-testing-no-run-as-node:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
- linux-x64-testing
|
||||
- linux-x64-testing-no-run-as-node
|
||||
- linux-x64-testing-gn-check:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
@@ -1717,12 +1886,8 @@ workflows:
|
||||
requires:
|
||||
- linux-x64-testing
|
||||
|
||||
- linux-ia32-debug:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
- linux-ia32-testing:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
- linux-ia32-debug
|
||||
- linux-ia32-testing
|
||||
- linux-ia32-testing-tests:
|
||||
requires:
|
||||
- linux-ia32-testing
|
||||
@@ -1733,27 +1898,20 @@ workflows:
|
||||
requires:
|
||||
- linux-ia32-testing
|
||||
|
||||
- linux-arm-debug:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
- linux-arm-testing:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
- linux-arm-debug
|
||||
- linux-arm-testing
|
||||
|
||||
- linux-arm64-debug:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
- linux-arm64-debug
|
||||
- linux-arm64-debug-gn-check:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
- linux-arm64-testing:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
- linux-arm64-testing
|
||||
- linux-arm64-testing-gn-check:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
|
||||
build-mac:
|
||||
when: << pipeline.parameters.run-build-mac >>
|
||||
jobs:
|
||||
- mac-checkout-fast
|
||||
- mac-checkout-and-save-cache
|
||||
@@ -1808,11 +1966,11 @@ workflows:
|
||||
- master
|
||||
- *chromium-upgrade-branches
|
||||
jobs:
|
||||
- linux-checkout
|
||||
- linux-checkout-fast
|
||||
|
||||
- linux-x64-release:
|
||||
requires:
|
||||
- linux-checkout
|
||||
- linux-checkout-fast
|
||||
- linux-x64-release-tests:
|
||||
requires:
|
||||
- linux-x64-release
|
||||
@@ -1824,7 +1982,7 @@ workflows:
|
||||
- linux-x64-release
|
||||
- linux-x64-chromedriver:
|
||||
requires:
|
||||
- linux-checkout
|
||||
- linux-checkout-fast
|
||||
- linux-x64-release-summary:
|
||||
requires:
|
||||
- linux-x64-release
|
||||
@@ -1834,7 +1992,7 @@ workflows:
|
||||
|
||||
- linux-ia32-release:
|
||||
requires:
|
||||
- linux-checkout
|
||||
- linux-checkout-fast
|
||||
- linux-ia32-release-tests:
|
||||
requires:
|
||||
- linux-ia32-release
|
||||
@@ -1846,7 +2004,7 @@ workflows:
|
||||
- linux-ia32-release
|
||||
- linux-ia32-chromedriver:
|
||||
requires:
|
||||
- linux-checkout
|
||||
- linux-checkout-fast
|
||||
- linux-ia32-release-summary:
|
||||
requires:
|
||||
- linux-ia32-release
|
||||
@@ -1856,10 +2014,10 @@ workflows:
|
||||
|
||||
- linux-arm-release:
|
||||
requires:
|
||||
- linux-checkout
|
||||
- linux-checkout-fast
|
||||
- linux-arm-chromedriver:
|
||||
requires:
|
||||
- linux-checkout
|
||||
- linux-checkout-fast
|
||||
- linux-arm-release-summary:
|
||||
requires:
|
||||
- linux-arm-release
|
||||
@@ -1868,10 +2026,10 @@ workflows:
|
||||
|
||||
- linux-arm64-release:
|
||||
requires:
|
||||
- linux-checkout
|
||||
- linux-checkout-fast
|
||||
- linux-arm64-chromedriver:
|
||||
requires:
|
||||
- linux-checkout
|
||||
- linux-checkout-fast
|
||||
- linux-arm64-release-summary:
|
||||
requires:
|
||||
- linux-arm64-release
|
||||
@@ -1887,11 +2045,11 @@ workflows:
|
||||
- master
|
||||
- *chromium-upgrade-branches
|
||||
jobs:
|
||||
- mac-checkout
|
||||
- mac-checkout-fast
|
||||
|
||||
- osx-release:
|
||||
requires:
|
||||
- mac-checkout
|
||||
- mac-checkout-fast
|
||||
- osx-release-tests:
|
||||
requires:
|
||||
- osx-release
|
||||
@@ -1903,7 +2061,7 @@ workflows:
|
||||
- osx-release
|
||||
- osx-chromedriver:
|
||||
requires:
|
||||
- mac-checkout
|
||||
- mac-checkout-fast
|
||||
- osx-release-summary:
|
||||
requires:
|
||||
- osx-release
|
||||
@@ -1913,7 +2071,7 @@ workflows:
|
||||
|
||||
- mas-release:
|
||||
requires:
|
||||
- mac-checkout
|
||||
- mac-checkout-fast
|
||||
- mas-release-tests:
|
||||
requires:
|
||||
- mas-release
|
||||
@@ -1925,7 +2083,7 @@ workflows:
|
||||
- mas-release
|
||||
- mas-chromedriver:
|
||||
requires:
|
||||
- mac-checkout
|
||||
- mac-checkout-fast
|
||||
- mas-release-summary:
|
||||
requires:
|
||||
- mas-release
|
||||
|
||||
10
.github/main.workflow
vendored
10
.github/main.workflow
vendored
@@ -1,10 +0,0 @@
|
||||
workflow "Clerk" {
|
||||
#TODO(codebytere): make this work properly on pull_request
|
||||
on = "repository_dispatch"
|
||||
resolves = "Check release notes"
|
||||
}
|
||||
|
||||
action "Check release notes" {
|
||||
uses = "electron/clerk@master"
|
||||
secrets = [ "GITHUB_TOKEN" ]
|
||||
}
|
||||
25
.github/stale.yml
vendored
25
.github/stale.yml
vendored
@@ -1,25 +0,0 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 45
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- fixme/bug
|
||||
- fixme/crash
|
||||
- fixme/regression
|
||||
- fixme/security
|
||||
- blocked
|
||||
- blocking-stable
|
||||
- needs-review
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity and is not currently prioritized. It will be closed
|
||||
in a week if no further activity occurs :)
|
||||
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: >
|
||||
If you still think this issue is relevant, please ping a maintainer or
|
||||
leave a comment!
|
||||
87
BUILD.gn
87
BUILD.gn
@@ -4,6 +4,7 @@ import("//build/config/win/manifest.gni")
|
||||
import("//content/public/app/mac_helpers.gni")
|
||||
import("//pdf/features.gni")
|
||||
import("//printing/buildflags/buildflags.gni")
|
||||
import("//testing/test.gni")
|
||||
import("//third_party/ffmpeg/ffmpeg_options.gni")
|
||||
import("//tools/generate_library_loader/generate_library_loader.gni")
|
||||
import("//tools/grit/grit_rule.gni")
|
||||
@@ -26,7 +27,6 @@ if (is_mac) {
|
||||
import("//third_party/icu/config.gni")
|
||||
import("//ui/gl/features.gni")
|
||||
import("//v8/gni/v8.gni")
|
||||
import("build/rules.gni")
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
@@ -61,6 +61,10 @@ config("branding") {
|
||||
]
|
||||
}
|
||||
|
||||
config("electron_lib_config") {
|
||||
include_dirs = [ "." ]
|
||||
}
|
||||
|
||||
# We geneate the definitions twice here, once in //electron/electron.d.ts
|
||||
# and once in $target_gen_dir
|
||||
# The one in $target_gen_dir is used for the actual TSC build later one
|
||||
@@ -281,6 +285,7 @@ if (is_linux) {
|
||||
"notify_notification_add_action",
|
||||
"notify_notification_set_image_from_pixbuf",
|
||||
"notify_notification_set_timeout",
|
||||
"notify_notification_set_urgency",
|
||||
"notify_notification_set_hint_string",
|
||||
"notify_notification_show",
|
||||
"notify_notification_close",
|
||||
@@ -333,7 +338,10 @@ source_set("electron_lib") {
|
||||
configs += [ "//v8:external_startup_data" ]
|
||||
configs += [ "//third_party/electron_node:node_internals" ]
|
||||
|
||||
public_configs = [ ":branding" ]
|
||||
public_configs = [
|
||||
":branding",
|
||||
":electron_lib_config",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":atom_js2c",
|
||||
@@ -475,6 +483,19 @@ source_set("electron_lib") {
|
||||
"//content/common:mac_helpers",
|
||||
"//ui/accelerated_widget_mac",
|
||||
]
|
||||
|
||||
libs = [
|
||||
"AVFoundation.framework",
|
||||
"Carbon.framework",
|
||||
"LocalAuthentication.framework",
|
||||
"QuartzCore.framework",
|
||||
"Quartz.framework",
|
||||
"Security.framework",
|
||||
"SecurityInterface.framework",
|
||||
"ServiceManagement.framework",
|
||||
"StoreKit.framework",
|
||||
]
|
||||
|
||||
sources += [
|
||||
"shell/browser/ui/views/autofill_popup_view.cc",
|
||||
"shell/browser/ui/views/autofill_popup_view.h",
|
||||
@@ -580,6 +601,17 @@ source_set("electron_lib") {
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_remote_module) {
|
||||
sources += [
|
||||
"shell/common/api/remote/object_life_monitor.cc",
|
||||
"shell/common/api/remote/object_life_monitor.h",
|
||||
"shell/common/api/remote/remote_callback_freer.cc",
|
||||
"shell/common/api/remote/remote_callback_freer.h",
|
||||
"shell/common/api/remote/remote_object_freer.cc",
|
||||
"shell/common/api/remote/remote_object_freer.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_desktop_capturer) {
|
||||
if (is_component_build && !is_linux) {
|
||||
# On windows the implementation relies on unexported
|
||||
@@ -656,12 +688,6 @@ if (is_mac) {
|
||||
electron_framework_version = "A"
|
||||
electron_version = read_file("ELECTRON_VERSION", "trim string")
|
||||
|
||||
mac_xib_bundle_data("electron_xibs") {
|
||||
sources = [
|
||||
"shell/common/resources/mac/MainMenu.xib",
|
||||
]
|
||||
}
|
||||
|
||||
bundle_data("electron_framework_resources") {
|
||||
public_deps = [
|
||||
":packed_resources",
|
||||
@@ -769,6 +795,7 @@ if (is_mac) {
|
||||
"Libraries",
|
||||
]
|
||||
public_deps = [
|
||||
":electron_framework_libraries",
|
||||
":electron_lib",
|
||||
]
|
||||
deps = [
|
||||
@@ -776,7 +803,6 @@ if (is_mac) {
|
||||
":electron_framework_libraries",
|
||||
":electron_framework_resources",
|
||||
":electron_swiftshader_library",
|
||||
":electron_xibs",
|
||||
]
|
||||
if (!is_mas_build) {
|
||||
deps += [ ":electron_crashpad_helper" ]
|
||||
@@ -791,18 +817,6 @@ if (is_mac) {
|
||||
include_dirs = [ "." ]
|
||||
sources = filenames.framework_sources
|
||||
|
||||
libs = [
|
||||
"AVFoundation.framework",
|
||||
"Carbon.framework",
|
||||
"LocalAuthentication.framework",
|
||||
"QuartzCore.framework",
|
||||
"Quartz.framework",
|
||||
"Security.framework",
|
||||
"SecurityInterface.framework",
|
||||
"ServiceManagement.framework",
|
||||
"StoreKit.framework",
|
||||
]
|
||||
|
||||
if (enable_osr) {
|
||||
libs += [ "IOSurface.framework" ]
|
||||
}
|
||||
@@ -1185,6 +1199,37 @@ if (is_mac) {
|
||||
}
|
||||
}
|
||||
|
||||
test("shell_browser_ui_unittests") {
|
||||
sources = [
|
||||
"//electron/shell/browser/ui/accelerator_util_unittests.cc",
|
||||
"//electron/shell/browser/ui/run_all_unittests.cc",
|
||||
]
|
||||
|
||||
configs += [ ":electron_lib_config" ]
|
||||
|
||||
deps = [
|
||||
":electron_lib",
|
||||
"//base",
|
||||
"//base/test:test_support",
|
||||
"//testing/gmock",
|
||||
"//testing/gtest",
|
||||
"//ui/base",
|
||||
"//ui/strings",
|
||||
]
|
||||
|
||||
if (is_mac) {
|
||||
# Resolve paths owing to different test executable locations
|
||||
ldflags = [
|
||||
"-F",
|
||||
rebase_path("external_binaries", root_build_dir),
|
||||
"-rpath",
|
||||
"@loader_path",
|
||||
"-rpath",
|
||||
"@executable_path/" + rebase_path("external_binaries", root_build_dir),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
template("dist_zip") {
|
||||
_runtime_deps_target = "${target_name}__deps"
|
||||
_runtime_deps_file =
|
||||
|
||||
6
DEPS
6
DEPS
@@ -11,9 +11,9 @@ gclient_gn_args = [
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'78.0.3904.130',
|
||||
'6c775c358b709f4353bc693623bf58820adf3918',
|
||||
'node_version':
|
||||
'v12.8.1',
|
||||
'v12.9.1',
|
||||
'nan_version':
|
||||
'2ee313aaca52e2b478965ac50eb5082520380d1b',
|
||||
|
||||
@@ -114,7 +114,7 @@ hooks = [
|
||||
'pattern': 'src/electron/script/update-external-binaries.py',
|
||||
'condition': 'download_external_binaries',
|
||||
'action': [
|
||||
'python3',
|
||||
'python',
|
||||
'src/electron/script/update-external-binaries.py',
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1 +1 @@
|
||||
7.1.10
|
||||
8.0.0-nightly.20191009
|
||||
@@ -83,10 +83,12 @@ build_script:
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- ninja -C out/Default electron:electron_dist_zip
|
||||
- ninja -C out/Default shell_browser_ui_unittests
|
||||
- ninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default third_party/electron_node:headers
|
||||
- appveyor PushArtifact out/Default/dist.zip
|
||||
- appveyor PushArtifact out/Default/shell_browser_ui_unittests.exe
|
||||
- appveyor PushArtifact out/Default/chromedriver.zip
|
||||
- appveyor PushArtifact out/ffmpeg/ffmpeg.zip
|
||||
- 7z a node_headers.zip out\Default\gen\node_headers
|
||||
@@ -103,6 +105,11 @@ build_script:
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
python electron\script\zip-symbols.py
|
||||
appveyor PushArtifact out/Default/symbols.zip
|
||||
} else {
|
||||
# It's useful to have pdb files when debugging testing builds that are
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
appveyor PushArtifact pdb.zip
|
||||
}
|
||||
- python electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
test_script:
|
||||
|
||||
@@ -18,6 +18,14 @@ steps:
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$pwd\src\out\Default\shell_browser_ui_unittests.exe"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/shell_browser_ui_unittests.exe"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
displayName: 'Download and extract native test executables for test'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$pwd\ffmpeg.zip"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/ffmpeg.zip"
|
||||
|
||||
@@ -3,7 +3,7 @@ use_jumbo_build = true
|
||||
root_extra_deps = [ "//electron" ]
|
||||
|
||||
# Registry of NMVs --> https://github.com/nodejs/node/blob/master/doc/abi_version_registry.json
|
||||
node_module_version = 75
|
||||
node_module_version = 76
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_typed_array_max_size_in_heap = 0
|
||||
@@ -24,3 +24,6 @@ is_cfi = false
|
||||
# TODO: Remove this and update CI to contain 10.14 SDK once
|
||||
# crbug.com/986701 is fixed.
|
||||
mac_sdk_min = "10.13"
|
||||
|
||||
# TODO: disabled due to crashes. re-enable.
|
||||
enable_osr = false
|
||||
|
||||
@@ -6,8 +6,6 @@ is_official_build = false
|
||||
dcheck_always_on = true
|
||||
symbol_level = 1
|
||||
|
||||
strip_absolute_paths_from_debug_symbols = false
|
||||
|
||||
# This may be guarded behind is_chrome_branded alongside
|
||||
# proprietary_codecs https://webrtc-review.googlesource.com/c/src/+/36321,
|
||||
# explicitly override here to build OpenH264 encoder/FFmpeg decoder.
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
import("//build/config/mac/mac_sdk.gni")
|
||||
|
||||
# This is imported from /ios becuase this functionality was moved
|
||||
# after Chromium stopped using xib files for macOS menu functionality
|
||||
# See https://chromium-review.googlesource.com/c/chromium/src/+/1648695
|
||||
import("//build/config/ios/rules.gni")
|
||||
|
||||
# Template is copied here from Chromium but was removed in
|
||||
# https://chromium-review.googlesource.com/c/chromium/src/+/1637981
|
||||
# Template to compile and package Mac XIB files as bundle data.
|
||||
# Arguments
|
||||
# sources:
|
||||
# list of string, sources to comiple
|
||||
# output_path:
|
||||
# (optional) string, the path to use for the outputs list in the
|
||||
# bundle_data step. If unspecified, defaults to bundle_resources_dir.
|
||||
template("mac_xib_bundle_data") {
|
||||
_target_name = target_name
|
||||
_compile_target_name = _target_name + "_compile_ibtool"
|
||||
|
||||
compile_ib_files(_compile_target_name) {
|
||||
forward_variables_from(invoker, [ "testonly" ])
|
||||
visibility = [ ":$_target_name" ]
|
||||
sources = invoker.sources
|
||||
output_extension = "nib"
|
||||
ibtool_flags = [
|
||||
"--minimum-deployment-target",
|
||||
mac_deployment_target,
|
||||
|
||||
# TODO(rsesek): Enable this once all the bots are on Xcode 7+.
|
||||
# "--target-device",
|
||||
# "mac",
|
||||
]
|
||||
}
|
||||
|
||||
bundle_data(_target_name) {
|
||||
forward_variables_from(invoker,
|
||||
[
|
||||
"testonly",
|
||||
"visibility",
|
||||
])
|
||||
|
||||
public_deps = [
|
||||
":$_compile_target_name",
|
||||
]
|
||||
sources = get_target_outputs(":$_compile_target_name")
|
||||
|
||||
_output_path = "{{bundle_resources_dir}}"
|
||||
if (defined(invoker.output_path)) {
|
||||
_output_path = invoker.output_path
|
||||
}
|
||||
|
||||
outputs = [
|
||||
"$_output_path/{{source_file_part}}",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ module.exports = ({
|
||||
resolve: {
|
||||
alias: {
|
||||
'@electron/internal': path.resolve(electronRoot, 'lib'),
|
||||
'electron': path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.js'),
|
||||
'electron': path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.ts'),
|
||||
// Force timers to resolve to our dependency that doens't use window.postMessage
|
||||
'timers': path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
|
||||
},
|
||||
@@ -74,10 +74,7 @@ module.exports = ({
|
||||
global: ['@electron/internal/renderer/webpack-provider', '_global'],
|
||||
Buffer: ['@electron/internal/renderer/webpack-provider', 'Buffer'],
|
||||
})
|
||||
] : []),
|
||||
new webpack.ProvidePlugin({
|
||||
Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise'],
|
||||
}),
|
||||
] : [])
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,6 @@ PATHS_TO_SKIP = [
|
||||
'./libVkICD_mock_', #Skipping because these are outputs that we don't need
|
||||
'./VkICD_mock_', #Skipping because these are outputs that we don't need
|
||||
|
||||
# Skipping because its an output of create_bundle from //build/config/mac/rules.gni
|
||||
# that we don't need
|
||||
'Electron.dSYM',
|
||||
|
||||
# //chrome/browser:resources depends on this via
|
||||
# //chrome/browser/resources/ssl/ssl_error_assistant, but we don't need to
|
||||
# ship it.
|
||||
@@ -55,13 +51,14 @@ def main(argv):
|
||||
with open(runtime_deps) as f:
|
||||
for dep in f.readlines():
|
||||
dep = dep.strip()
|
||||
if not skip_path(dep, dist_zip, target_cpu):
|
||||
dist_files.add(dep)
|
||||
dist_files.add(dep)
|
||||
if sys.platform == 'darwin':
|
||||
execute(['zip', '-r', '-y', dist_zip] + list(dist_files))
|
||||
else:
|
||||
with zipfile.ZipFile(dist_zip, 'w', zipfile.ZIP_DEFLATED, allowZip64=True) as z:
|
||||
for dep in dist_files:
|
||||
if skip_path(dep, dist_zip, target_cpu):
|
||||
continue
|
||||
if os.path.isdir(dep):
|
||||
for root, dirs, files in os.walk(dep):
|
||||
for file in files:
|
||||
|
||||
@@ -12,6 +12,7 @@ buildflag_header("buildflags") {
|
||||
"ENABLE_DESKTOP_CAPTURER=$enable_desktop_capturer",
|
||||
"ENABLE_RUN_AS_NODE=$enable_run_as_node",
|
||||
"ENABLE_OSR=$enable_osr",
|
||||
"ENABLE_REMOTE_MODULE=$enable_remote_module",
|
||||
"ENABLE_VIEW_API=$enable_view_api",
|
||||
"ENABLE_PEPPER_FLASH=$enable_pepper_flash",
|
||||
"ENABLE_PDF_VIEWER=$enable_pdf_viewer",
|
||||
@@ -19,7 +20,6 @@ buildflag_header("buildflags") {
|
||||
"ENABLE_COLOR_CHOOSER=$enable_color_chooser",
|
||||
"ENABLE_ELECTRON_EXTENSIONS=$enable_electron_extensions",
|
||||
"ENABLE_PICTURE_IN_PICTURE=$enable_picture_in_picture",
|
||||
"ENABLE_MEDIA_KEY_OVERRIDES=$enable_media_key_overrides",
|
||||
"OVERRIDE_LOCATION_PROVIDER=$enable_fake_location_provider",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ declare_args() {
|
||||
|
||||
enable_osr = true
|
||||
|
||||
enable_remote_module = true
|
||||
|
||||
enable_view_api = false
|
||||
|
||||
enable_pdf_viewer = false
|
||||
@@ -20,8 +22,6 @@ declare_args() {
|
||||
|
||||
enable_picture_in_picture = true
|
||||
|
||||
enable_media_key_overrides = true
|
||||
|
||||
# Provide a fake location provider for mocking
|
||||
# the geolocation responses. Disable it if you
|
||||
# need to test with chromium's location provider.
|
||||
|
||||
@@ -43,6 +43,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/predictors/proxy_lookup_client_impl.h",
|
||||
"//chrome/browser/predictors/resolve_host_client_impl.cc",
|
||||
"//chrome/browser/predictors/resolve_host_client_impl.h",
|
||||
"//chrome/browser/printing/printing_service.cc",
|
||||
"//chrome/browser/printing/printing_service.h",
|
||||
"//chrome/browser/ssl/security_state_tab_helper.cc",
|
||||
"//chrome/browser/ssl/security_state_tab_helper.h",
|
||||
"//chrome/browser/ui/autofill/popup_view_common.cc",
|
||||
@@ -162,8 +164,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/printing/printer_query.h",
|
||||
"//chrome/browser/printing/printing_message_filter.cc",
|
||||
"//chrome/browser/printing/printing_message_filter.h",
|
||||
"//chrome/browser/printing/printing_service.cc",
|
||||
"//chrome/browser/printing/printing_service.h",
|
||||
]
|
||||
|
||||
public_deps += [
|
||||
|
||||
@@ -73,7 +73,7 @@ net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
|
||||
void CertificateManagerModel::Create(content::BrowserContext* browser_context,
|
||||
const CreationCallback& callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
base::PostTaskWithTraits(
|
||||
base::PostTask(
|
||||
FROM_HERE, {BrowserThread::IO},
|
||||
base::BindOnce(&CertificateManagerModel::GetCertDBOnIOThread,
|
||||
browser_context->GetResourceContext(), callback));
|
||||
@@ -86,7 +86,7 @@ CertificateManagerModel::CertificateManagerModel(
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
}
|
||||
|
||||
CertificateManagerModel::~CertificateManagerModel() {}
|
||||
CertificateManagerModel::~CertificateManagerModel() = default;
|
||||
|
||||
int CertificateManagerModel::ImportFromPKCS12(
|
||||
PK11SlotInfo* slot_info,
|
||||
@@ -146,7 +146,7 @@ void CertificateManagerModel::DidGetCertDBOnIOThread(
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
bool is_user_db_available = !!cert_db->GetPublicSlot();
|
||||
base::PostTaskWithTraits(
|
||||
base::PostTask(
|
||||
FROM_HERE, {BrowserThread::UI},
|
||||
base::BindOnce(&CertificateManagerModel::DidGetCertDBOnUIThread, cert_db,
|
||||
is_user_db_available, callback));
|
||||
|
||||
@@ -93,7 +93,6 @@
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "net/base/network_interfaces.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
|
||||
#include "ui/views/linux_ui/linux_ui.h"
|
||||
@@ -185,7 +184,7 @@ int WaitSocketForRead(int fd, const base::TimeDelta& timeout) {
|
||||
FD_ZERO(&read_fds);
|
||||
FD_SET(fd, &read_fds);
|
||||
|
||||
return HANDLE_EINTR(select(fd + 1, &read_fds, NULL, NULL, &tv));
|
||||
return HANDLE_EINTR(select(fd + 1, &read_fds, nullptr, nullptr, &tv));
|
||||
}
|
||||
|
||||
// Read a message from a socket fd, with an optional timeout.
|
||||
@@ -705,7 +704,7 @@ void ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK(
|
||||
if (shutdown(fd_, SHUT_WR) < 0)
|
||||
PLOG(ERROR) << "shutdown() failed";
|
||||
|
||||
base::PostTaskWithTraits(
|
||||
base::PostTask(
|
||||
FROM_HERE, {BrowserThread::IO},
|
||||
base::BindOnce(&ProcessSingleton::LinuxWatcher::RemoveSocketReader,
|
||||
parent_, this));
|
||||
@@ -885,10 +884,9 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessOrCreate() {
|
||||
|
||||
void ProcessSingleton::StartListeningOnSocket() {
|
||||
watcher_ = new LinuxWatcher(this);
|
||||
base::PostTaskWithTraits(
|
||||
FROM_HERE, {BrowserThread::IO},
|
||||
base::BindOnce(&ProcessSingleton::LinuxWatcher::StartListening, watcher_,
|
||||
sock_));
|
||||
base::PostTask(FROM_HERE, {BrowserThread::IO},
|
||||
base::BindOnce(&ProcessSingleton::LinuxWatcher::StartListening,
|
||||
watcher_, sock_));
|
||||
}
|
||||
|
||||
void ProcessSingleton::OnBrowserReady() {
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "chrome/browser/win/chrome_process_finder.h"
|
||||
#include "content/public/common/result_codes.h"
|
||||
#include "net/base/escape.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/gfx/win/hwnd_util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
<head>
|
||||
<title>Electron</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'sha256-6PH54BfkNq/EMMhUY7nhHf3c+AxloOwfy7hWyT01CM8='; style-src 'self'; img-src 'self'; connect-src 'self'" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'; connect-src 'self'" />
|
||||
<link href="./styles.css" type="text/css" rel="stylesheet" />
|
||||
<link href="./octicon/build.css" type="text/css" rel="stylesheet" />
|
||||
<script defer src="./index.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -83,9 +84,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<script>
|
||||
window.electronDefaultApp.initialize()
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
30
default_app/index.ts
Normal file
30
default_app/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
async function getOcticonSvg (name: string) {
|
||||
try {
|
||||
const response = await fetch(`octicon/${name}.svg`)
|
||||
const div = document.createElement('div')
|
||||
div.innerHTML = await response.text()
|
||||
return div
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSVG (element: HTMLSpanElement) {
|
||||
for (const cssClass of element.classList) {
|
||||
if (cssClass.startsWith('octicon-')) {
|
||||
const icon = await getOcticonSvg(cssClass.substr(8))
|
||||
if (icon) {
|
||||
for (const elemClass of element.classList) {
|
||||
icon.classList.add(elemClass)
|
||||
}
|
||||
element.before(icon)
|
||||
element.remove()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const element of document.querySelectorAll<HTMLSpanElement>('.octicon')) {
|
||||
loadSVG(element)
|
||||
}
|
||||
@@ -1,31 +1,4 @@
|
||||
import { ipcRenderer, contextBridge } from 'electron'
|
||||
|
||||
async function getOcticonSvg (name: string) {
|
||||
try {
|
||||
const response = await fetch(`octicon/${name}.svg`)
|
||||
const div = document.createElement('div')
|
||||
div.innerHTML = await response.text()
|
||||
return div
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSVG (element: HTMLSpanElement) {
|
||||
for (const cssClass of element.classList) {
|
||||
if (cssClass.startsWith('octicon-')) {
|
||||
const icon = await getOcticonSvg(cssClass.substr(8))
|
||||
if (icon) {
|
||||
for (const elemClass of element.classList) {
|
||||
icon.classList.add(elemClass)
|
||||
}
|
||||
element.before(icon)
|
||||
element.remove()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
import { ipcRenderer } from 'electron'
|
||||
|
||||
async function initialize () {
|
||||
const electronPath = await ipcRenderer.invoke('bootstrap')
|
||||
@@ -42,12 +15,6 @@ async function initialize () {
|
||||
replaceText('.node-version', `Node v${process.versions.node}`)
|
||||
replaceText('.v8-version', `v8 v${process.versions.v8}`)
|
||||
replaceText('.command-example', `${electronPath} path-to-app`)
|
||||
|
||||
for (const element of document.querySelectorAll<HTMLSpanElement>('.octicon')) {
|
||||
loadSVG(element)
|
||||
}
|
||||
}
|
||||
|
||||
contextBridge.exposeInMainWorld('electronDefaultApp', {
|
||||
initialize
|
||||
})
|
||||
document.addEventListener('DOMContentLoaded', initialize)
|
||||
|
||||
@@ -39,7 +39,6 @@ an issue:
|
||||
* [Using Electron's APIs](tutorial/application-architecture.md#using-electron-apis)
|
||||
* [Using Node.js APIs](tutorial/application-architecture.md#using-nodejs-apis)
|
||||
* [Using Native Node.js Modules](tutorial/using-native-node-modules.md)
|
||||
* [Performance Strategies](tutorial/performance.md)
|
||||
* Adding Features to Your App
|
||||
* [Notifications](tutorial/notifications.md)
|
||||
* [Recent Documents](tutorial/recent-documents.md)
|
||||
@@ -109,7 +108,7 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
|
||||
* [Synopsis](api/synopsis.md)
|
||||
* [Process Object](api/process.md)
|
||||
* [Supported Chrome Command Line Switches](api/chrome-command-line-switches.md)
|
||||
* [Supported Command Line Switches](api/command-line-switches.md)
|
||||
* [Environment Variables](api/environment-variables.md)
|
||||
* [Breaking API Changes](api/breaking-changes.md)
|
||||
|
||||
@@ -135,6 +134,7 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
* [MenuItem](api/menu-item.md)
|
||||
* [net](api/net.md)
|
||||
* [netLog](api/net-log.md)
|
||||
* [Notification](api/notification.md)
|
||||
* [powerMonitor](api/power-monitor.md)
|
||||
* [powerSaveBlocker](api/power-save-blocker.md)
|
||||
* [protocol](api/protocol.md)
|
||||
|
||||
@@ -314,8 +314,10 @@ Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `authenticationResponseDetails` Object
|
||||
* `request` Object
|
||||
* `method` String
|
||||
* `url` URL
|
||||
* `referrer` URL
|
||||
* `authInfo` Object
|
||||
* `isProxy` Boolean
|
||||
* `scheme` String
|
||||
@@ -323,8 +325,8 @@ Returns:
|
||||
* `port` Integer
|
||||
* `realm` String
|
||||
* `callback` Function
|
||||
* `username` String (optional)
|
||||
* `password` String (optional)
|
||||
* `username` String
|
||||
* `password` String
|
||||
|
||||
Emitted when `webContents` wants to do basic auth.
|
||||
|
||||
@@ -335,16 +337,12 @@ should prevent the default behavior with `event.preventDefault()` and call
|
||||
```javascript
|
||||
const { app } = require('electron')
|
||||
|
||||
app.on('login', (event, webContents, details, authInfo, callback) => {
|
||||
app.on('login', (event, webContents, request, authInfo, callback) => {
|
||||
event.preventDefault()
|
||||
callback('username', 'secret')
|
||||
})
|
||||
```
|
||||
|
||||
If `callback` is called without a username or password, the authentication
|
||||
request will be cancelled and the authentication error will be returned to the
|
||||
page.
|
||||
|
||||
### Event: 'gpu-info-update'
|
||||
|
||||
Emitted whenever there is a GPU info update.
|
||||
@@ -392,7 +390,7 @@ Emitted when Electron has created a new `session`.
|
||||
```javascript
|
||||
const { app } = require('electron')
|
||||
|
||||
app.on('session-created', (event, session) => {
|
||||
app.on('session-created', (session) => {
|
||||
console.log(session)
|
||||
})
|
||||
```
|
||||
@@ -677,13 +675,15 @@ preferred over `name` by Electron.
|
||||
|
||||
Overrides the current application's name.
|
||||
|
||||
**Note:** This function overrides the name used internally by Electron; it does not affect the name that the OS uses.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `app.getLocale()`
|
||||
|
||||
Returns `String` - The current application locale. Possible return values are documented [here](locales.md).
|
||||
|
||||
To set the locale, you'll want to use a command line switch at app startup, which may be found [here](https://github.com/electron/electron/blob/master/docs/api/chrome-command-line-switches.md).
|
||||
To set the locale, you'll want to use a command line switch at app startup, which may be found [here](https://github.com/electron/electron/blob/master/docs/api/command-line-switches.md).
|
||||
|
||||
**Note:** When distributing your packaged app, you have to also ship the
|
||||
`locales` folder.
|
||||
@@ -1170,21 +1170,21 @@ This API must be called after the `ready` event is emitted.
|
||||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `app.showAboutPanel()` _macOS_ _Linux_
|
||||
### `app.showAboutPanel()`
|
||||
|
||||
Show the app's about panel options. These options can be overridden with `app.setAboutPanelOptions(options)`.
|
||||
|
||||
### `app.setAboutPanelOptions(options)` _macOS_ _Linux_
|
||||
### `app.setAboutPanelOptions(options)`
|
||||
|
||||
* `options` Object
|
||||
* `applicationName` String (optional) - The app's name.
|
||||
* `applicationVersion` String (optional) - The app's version.
|
||||
* `copyright` String (optional) - Copyright information.
|
||||
* `version` String (optional) _macOS_ - The app's build version number.
|
||||
* `credits` String (optional) _macOS_ - Credit information.
|
||||
* `credits` String (optional) _macOS_ _Windows_ - Credit information.
|
||||
* `authors` String[] (optional) _Linux_ - List of app authors.
|
||||
* `website` String (optional) _Linux_ - The app's website.
|
||||
* `iconPath` String (optional) _Linux_ - Path to the app's icon. Will be shown as 64x64 pixels while retaining aspect ratio.
|
||||
* `iconPath` String (optional) _Linux_ _Windows_ - Path to the app's icon. On Linux, will be shown as 64x64 pixels while retaining aspect ratio.
|
||||
|
||||
Set the about panel options. This will override the values defined in the app's
|
||||
`.plist` file on MacOS. See the [Apple docs][about-panel-options] for more details. On Linux, values must be set in order to be shown; there are no defaults.
|
||||
|
||||
@@ -68,40 +68,6 @@ webFrame.setIsolatedWorldInfo(
|
||||
|
||||
This property was removed in Chromium 77, and as such is no longer available.
|
||||
|
||||
### `webkitdirectory` attribute for `<input type="file"/>`
|
||||

|
||||
The `webkitdirectory` property on HTML file inputs allows them to select folders.
|
||||
Previous versions of Electron had an incorrect implementation where the `event.target.files`
|
||||
of the input returned a `FileList` that returned one `File` corresponding to the selected folder.
|
||||

|
||||
As of Electron 7, that `FileList` is now list of all files contained within
|
||||
the folder, similarly to Chrome, Firefox, and Edge
|
||||
([link to MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/webkitdirectory)).
|
||||

|
||||
As an illustration, take a folder with this structure:
|
||||
```console
|
||||
folder
|
||||
├── file1
|
||||
├── file2
|
||||
└── file3
|
||||
```
|
||||

|
||||
In Electron <=6, this would return a `FileList` with a `File` object for:
|
||||
```console
|
||||
path/to/folder
|
||||
```
|
||||

|
||||
In Electron 7, this now returns a `FileList` with a `File` object for:
|
||||
```console
|
||||
/path/to/folder/file3
|
||||
/path/to/folder/file2
|
||||
/path/to/folder/file1
|
||||
```
|
||||

|
||||
Note that `webkitdirectory` no longer exposes the path to the selected folder.
|
||||
If you require the path to the selected folder rather than the folder contents,
|
||||
see the `dialog.showOpenDialog` API ([link](https://github.com/electron/electron/blob/master/docs/api/dialog.md#dialogshowopendialogbrowserwindow-options)).
|
||||
|
||||
## Planned Breaking API Changes (6.0)
|
||||
|
||||
### `win.setMenu(null)`
|
||||
@@ -231,7 +197,7 @@ A new API, `protocol.registerSchemesAsPrivileged` has been added and should be u
|
||||
### webFrame Isolated World APIs
|
||||
|
||||
```js
|
||||
// Removed in Electron 7.0
|
||||
// Deprecated
|
||||
webFrame.setIsolatedWorldContentSecurityPolicy(worldId, csp)
|
||||
webFrame.setIsolatedWorldHumanReadableName(worldId, name)
|
||||
webFrame.setIsolatedWorldSecurityOrigin(worldId, securityOrigin)
|
||||
|
||||
@@ -206,8 +206,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `backgroundColor` String (optional) - Window's background color as a hexadecimal value,
|
||||
like `#66CD00` or `#FFF` or `#80FFFFFF` (alpha in #AARRGGBB format is supported if
|
||||
`transparent` is set to `true`). Default is `#FFF` (white).
|
||||
* `hasShadow` Boolean (optional) - Whether window should have a shadow. This is only
|
||||
implemented on macOS. Default is `true`.
|
||||
* `hasShadow` Boolean (optional) - Whether window should have a shadow. Default is `true`.
|
||||
* `opacity` Number (optional) - Set the initial opacity of the window, between 0.0 (fully
|
||||
transparent) and 1.0 (fully opaque). This is only implemented on Windows and macOS.
|
||||
* `darkTheme` Boolean (optional) - Forces using dark theme for the window, only works on
|
||||
@@ -383,6 +382,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `disableHtmlFullscreenWindowResize` Boolean (optional) - Whether to
|
||||
prevent the window from resizing when entering HTML Fullscreen. Default
|
||||
is `false`.
|
||||
* `accessibleTitle` String (optional) - An alternative title string provided only
|
||||
to accessibility tools such as screen readers. This string is not directly
|
||||
visible to users.
|
||||
|
||||
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
|
||||
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
|
||||
@@ -513,7 +515,7 @@ Emitted when the window is restored from a minimized state.
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `newBounds` [Rectangle](structures/rectangle.md) - Size the window is being resized to.
|
||||
* `newBounds` [`Rectangle`](structures/rectangle.md) - Size the window is being resized to.
|
||||
|
||||
Emitted before the window is resized. Calling `event.preventDefault()` will prevent the window from being resized.
|
||||
|
||||
@@ -523,14 +525,14 @@ Note that this is only emitted when the window is being resized manually. Resizi
|
||||
|
||||
Emitted after the window has been resized.
|
||||
|
||||
#### Event: 'will-move' _Windows_
|
||||
#### Event: 'will-move' _macOS_ _Windows_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `newBounds` [Rectangle](structures/rectangle.md) - Location the window is being moved to.
|
||||
* `newBounds` [`Rectangle`](structures/rectangle.md) - Location the window is being moved to.
|
||||
|
||||
Emitted before the window is moved. Calling `event.preventDefault()` will prevent the window from being moved.
|
||||
Emitted before the window is moved. On Windows, calling `event.preventDefault()` will prevent the window from being moved.
|
||||
|
||||
Note that this is only emitted when the window is being resized manually. Resizing the window with `setBounds`/`setSize` will not emit this event.
|
||||
|
||||
@@ -662,7 +664,8 @@ Returns `BrowserWindow | null` - The window that is focused in this application,
|
||||
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
|
||||
Returns `BrowserWindow` - The window that owns the given `webContents`.
|
||||
Returns `BrowserWindow | null` - The window that owns the given `webContents`
|
||||
or `null` if the contents are not owned by a window.
|
||||
|
||||
#### `BrowserWindow.fromBrowserView(browserView)`
|
||||
|
||||
@@ -828,6 +831,12 @@ const menu = Menu.buildFromTemplate(template)
|
||||
Menu.setApplicationMenu(menu)
|
||||
```
|
||||
|
||||
#### `win.accessibleTitle`
|
||||
|
||||
A `String` property that defines an alternative title provided only to
|
||||
accessibility tools such as screen readers. This string is not directly
|
||||
visible to users.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
Objects created with `new BrowserWindow` have the following instance methods:
|
||||
@@ -1201,6 +1210,14 @@ can not be focused on.
|
||||
|
||||
Returns `Boolean` - Whether the window is always on top of other windows.
|
||||
|
||||
#### `win.moveAbove(mediaSourceId)`
|
||||
|
||||
* `mediaSourceId` String - Window id in the format of DesktopCapturerSource's id. For example "window:1869:0".
|
||||
|
||||
Moves window above the source window in the sense of z-order. If the
|
||||
`mediaSourceId` is not of type window or if the window does not exist then
|
||||
this method throws an error.
|
||||
|
||||
#### `win.moveTop()`
|
||||
|
||||
Moves window to top(z-order) regardless of focus
|
||||
@@ -1273,6 +1290,15 @@ Enters or leaves the kiosk mode.
|
||||
|
||||
Returns `Boolean` - Whether the window is in kiosk mode.
|
||||
|
||||
#### `win.getMediaSourceId()`
|
||||
|
||||
Returns `String` - Window id in the format of DesktopCapturerSource's id. For example "window:1234:0".
|
||||
|
||||
More precisely the format is `window:id:other_id` where `id` is `HWND` on
|
||||
Windows, `CGWindowID` (`uint64_t`) on macOS and `Window` (`unsigned long`) on
|
||||
Linux. `other_id` is used to identify web contents (tabs) so within the same
|
||||
top level window.
|
||||
|
||||
#### `win.getNativeWindowHandle()`
|
||||
|
||||
Returns `Buffer` - The platform-specific handle of the window.
|
||||
@@ -1553,7 +1579,7 @@ Same as `webContents.showDefinitionForSelection()`.
|
||||
|
||||
#### `win.setIcon(icon)` _Windows_ _Linux_
|
||||
|
||||
* `icon` [NativeImage](native-image.md) | String
|
||||
* `icon` [NativeImage](native-image.md)
|
||||
|
||||
Changes window icon.
|
||||
|
||||
@@ -1720,14 +1746,14 @@ removed in future Electron releases.
|
||||
|
||||
#### `win.setBrowserView(browserView)` _Experimental_
|
||||
|
||||
* `browserView` [BrowserView](browser-view.md) | null - Attach browserView to win.
|
||||
If there is some other browserViews was attached they will be removed from
|
||||
* `browserView` [BrowserView](browser-view.md) | null - Attach `browserView` to `win`.
|
||||
If there are other `BrowserView`s attached, they will be removed from
|
||||
this window.
|
||||
|
||||
#### `win.getBrowserView()` _Experimental_
|
||||
|
||||
Returns `BrowserView | null` - an BrowserView what is attached. Returns `null`
|
||||
if none is attached. Throw error if multiple BrowserViews is attached.
|
||||
Returns `BrowserView | null` - The `BrowserView` attached to `win`. Returns `null`
|
||||
if one is not attached. Throws an error if multiple `BrowserView`s are attached.
|
||||
|
||||
#### `win.addBrowserView(browserView)` _Experimental_
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ the hostname and the port number 'hostname:port'.
|
||||
* `redirect` String (optional) - The redirect mode for this request. Should be
|
||||
one of `follow`, `error` or `manual`. Defaults to `follow`. When mode is `error`,
|
||||
any redirection will be aborted. When mode is `manual` the redirection will be
|
||||
cancelled unless [`request.followRedirect`](#requestfollowredirect) is invoked
|
||||
synchronously during the [`redirect`](#event-redirect) event.
|
||||
deferred until [`request.followRedirect`](#requestfollowredirect) is invoked. Listen for the [`redirect`](#event-redirect) event in
|
||||
this mode to get more details about the redirect request.
|
||||
|
||||
`options` properties such as `protocol`, `host`, `hostname`, `port` and `path`
|
||||
strictly follow the Node.js model as described in the
|
||||
@@ -70,8 +70,8 @@ Returns:
|
||||
* `port` Integer
|
||||
* `realm` String
|
||||
* `callback` Function
|
||||
* `username` String (optional)
|
||||
* `password` String (optional)
|
||||
* `username` String
|
||||
* `password` String
|
||||
|
||||
Emitted when an authenticating proxy is asking for user credentials.
|
||||
|
||||
@@ -136,11 +136,8 @@ Returns:
|
||||
* `redirectUrl` String
|
||||
* `responseHeaders` Record<String, String[]>
|
||||
|
||||
Emitted when the server returns a redirect response (e.g. 301 Moved
|
||||
Permanently). Calling [`request.followRedirect`](#requestfollowredirect) will
|
||||
continue with the redirection. If this event is handled,
|
||||
[`request.followRedirect`](#requestfollowredirect) must be called
|
||||
**synchronously**, otherwise the request will be cancelled.
|
||||
Emitted when there is redirection and the mode is `manual`. Calling
|
||||
[`request.followRedirect`](#requestfollowredirect) will continue with the redirection.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
@@ -217,8 +214,7 @@ response object,it will emit the `aborted` event.
|
||||
|
||||
#### `request.followRedirect()`
|
||||
|
||||
Continues any pending redirection. Can only be called during a `'redirect'`
|
||||
event.
|
||||
Continues any deferred redirection request when the redirection mode is `manual`.
|
||||
|
||||
#### `request.getUploadProgress()`
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Supported Chrome Command Line Switches
|
||||
# Supported Command Line Switches
|
||||
|
||||
> Command line switches supported by Electron.
|
||||
|
||||
@@ -181,6 +181,17 @@ logging level for all code in the source files under a `foo/bar` directory.
|
||||
|
||||
This switch only works when `--enable-logging` is also passed.
|
||||
|
||||
## --enable-api-filtering-logging
|
||||
|
||||
Enables caller stack logging for the following APIs (filtering events):
|
||||
- `desktopCapturer.getSources()` / `desktop-capturer-get-sources`
|
||||
- `remote.require()` / `remote-require`
|
||||
- `remote.getGlobal()` / `remote-get-builtin`
|
||||
- `remote.getBuiltin()` / `remote-get-global`
|
||||
- `remote.getCurrentWindow()` / `remote-get-current-window`
|
||||
- `remote.getCurrentWebContents()` / `remote-get-current-web-contents`
|
||||
- `remote.getGuestWebContents()` / `remote-get-guest-web-contents`
|
||||
|
||||
## --no-sandbox
|
||||
|
||||
Disables Chromium sandbox, which is now enabled by default.
|
||||
@@ -12,7 +12,7 @@ app.commandLine.hasSwitch('disable-gpu')
|
||||
```
|
||||
|
||||
For more information on what kinds of flags and switches you can use, check
|
||||
out the [Chrome Command Line Switches](./chrome-command-line-switches.md)
|
||||
out the [Command Line Switches](./command-line-switches.md)
|
||||
document.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
# contextBridge
|
||||
|
||||
> Create a safe, bi-directional, synchronous bridge across isolated contexts
|
||||
|
||||
Process: [Renderer](../glossary.md#renderer-process)
|
||||
|
||||
An example of exposing an API to a renderer from an isolated preload script is given below:
|
||||
|
||||
```javascript
|
||||
// Preload (Isolated World)
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld(
|
||||
'electron',
|
||||
{
|
||||
doThing: () => ipcRenderer.send('do-a-thing')
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Renderer (Main World)
|
||||
|
||||
window.electron.doThing()
|
||||
```
|
||||
|
||||
## Glossary
|
||||
|
||||
### Main World
|
||||
|
||||
The "Main World" is the javascript context that your main renderer code runs in. By default the page you load in your renderer
|
||||
executes code in this world.
|
||||
|
||||
### Isolated World
|
||||
|
||||
When `contextIsolation` is enabled in your `webPreferences` your `preload` scripts run in an "Isolated World". You can read more about
|
||||
context isolation and what it affects in the [BrowserWindow](browser-window.md) docs.
|
||||
|
||||
## Methods
|
||||
|
||||
The `contextBridge` module has the following methods:
|
||||
|
||||
### `contextBridge.exposeInMainWorld(apiKey, api)` _Experimental_
|
||||
|
||||
* `apiKey` String - The key to inject the API onto `window` with. The API will be accessible on `window[apiKey]`.
|
||||
* `api` Record<String, any> - Your API object, more information on what this API can be and how it works is available below.
|
||||
|
||||
## Usage
|
||||
|
||||
### API Objects
|
||||
|
||||
The `api` object provided to [`exposeInMainWorld`](#contextbridgeexposeinmainworldapikey-api-experimental) must be an object
|
||||
whose keys are strings and values are a `Function`, `String`, `Number`, `Array`, `Boolean` or another nested object that meets the same conditions.
|
||||
|
||||
`Function` values are proxied to the other context and all other values are **copied** and **frozen**. I.e. Any data / primitives sent in
|
||||
the API object become immutable and updates on either side of the bridge do not result in an update on the other side.
|
||||
|
||||
An example of a complex API object is shown below.
|
||||
|
||||
```javascript
|
||||
const { contextBridge } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld(
|
||||
'electron',
|
||||
{
|
||||
doThing: () => ipcRenderer.send('do-a-thing'),
|
||||
myPromises: [Promise.resolve(), Promise.reject(new Error('whoops'))],
|
||||
anAsyncFunction: async () => 123,
|
||||
data: {
|
||||
myFlags: ['a', 'b', 'c'],
|
||||
bootTime: 1234
|
||||
},
|
||||
nestedAPI: {
|
||||
evenDeeper: {
|
||||
youCanDoThisAsMuchAsYouWant: {
|
||||
fn: () => ({
|
||||
returnData: 123
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### API Functions
|
||||
|
||||
`Function` values that you bind through the `contextBridge` are proxied through Electron to ensure that contexts remain isolated. This
|
||||
results in some key limitations that we've outlined below.
|
||||
|
||||
#### Parameter / Error / Return Type support
|
||||
|
||||
Because parameters, errors and return values are **copied** when they are sent over the bridge there are only certain types that can be used.
|
||||
At a high level if the type you want to use can be serialized and un-serialized into the same object it will work. A table of type support
|
||||
has been included below for completeness.
|
||||
|
||||
| Type | Complexity | Parameter Support | Return Value Support | Limitations |
|
||||
| ---- | ---------- | ----------------- | -------------------- | ----------- |
|
||||
| `String` | Simple | ✅ | ✅ | N/A |
|
||||
| `Number` | Simple | ✅ | ✅ | N/A |
|
||||
| `Boolean` | Simple | ✅ | ✅ | N/A |
|
||||
| `Object` | Complex | ✅ | ✅ | Keys must be supported "Simple" types in this table. Values must be supported in this table. Prototype modifications are dropped. Sending custom classes will copy values but not the prototype. |
|
||||
| `Array` | Complex | ✅ | ✅ | Same limitations as the `Object` type |
|
||||
| `Error` | Complex | ✅ | ✅ | Errors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context |
|
||||
| `Promise` | Complex | ✅ | ✅ | Promises are only proxied if they are a the return value or exact parameter. Promises nested in arrays or obejcts will be dropped. |
|
||||
| `Function` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending classes or constructors will not work. |
|
||||
| [Cloneable Types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) | Simple | ✅ | ✅ | See the linked document on cloneable types |
|
||||
| `Symbol` | N/A | ❌ | ❌ | Symbols cannot be copied across contexts so they are dropped |
|
||||
|
||||
|
||||
If the type you care about is not in the above table it is probably not supported.
|
||||
@@ -48,6 +48,7 @@ The `dialog` module has the following methods:
|
||||
their target path.
|
||||
* `treatPackageAsDirectory` _macOS_ - Treat packages, such as `.app` folders,
|
||||
as a directory instead of a file.
|
||||
* `dontAddToRecent` _Windows_ - Do not add the item being opened to the recent documents list.
|
||||
* `message` String (optional) _macOS_ - Message to display above input
|
||||
boxes.
|
||||
* `securityScopedBookmarks` Boolean (optional) _macOS_ _mas_ - Create [security scoped bookmarks](https://developer.apple.com/library/content/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW16) when packaged for the Mac App Store.
|
||||
@@ -110,6 +111,7 @@ dialog.showOpenDialogSync(mainWindow, {
|
||||
their target path.
|
||||
* `treatPackageAsDirectory` _macOS_ - Treat packages, such as `.app` folders,
|
||||
as a directory instead of a file.
|
||||
* `dontAddToRecent` _Windows_ - Do not add the item being opened to the recent documents list.
|
||||
* `message` String (optional) _macOS_ - Message to display above input
|
||||
boxes.
|
||||
* `securityScopedBookmarks` Boolean (optional) _macOS_ _mas_ - Create [security scoped bookmarks](https://developer.apple.com/library/content/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW16) when packaged for the Mac App Store.
|
||||
@@ -171,6 +173,13 @@ dialog.showOpenDialog(mainWindow, {
|
||||
displayed in front of the filename text field.
|
||||
* `showsTagField` Boolean (optional) _macOS_ - Show the tags input box,
|
||||
defaults to `true`.
|
||||
* `properties` String[] (optional)
|
||||
* `showHiddenFiles` - Show hidden files in dialog.
|
||||
* `createDirectory` _macOS_ - Allow creating new directories from dialog.
|
||||
* `treatPackageAsDirectory` _macOS_ - Treat packages, such as `.app` folders,
|
||||
as a directory instead of a file.
|
||||
* `showOverwriteConfirmation` _Linux_ - Sets whether the user will be presented a confirmation dialog if the user types a file name that already exists.
|
||||
* `dontAddToRecent` _Windows_ - Do not add the item being saved to the recent documents list.
|
||||
* `securityScopedBookmarks` Boolean (optional) _macOS_ _mas_ - Create a [security scoped bookmark](https://developer.apple.com/library/content/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW16) when packaged for the Mac App Store. If this option is enabled and the file doesn't already exist a blank file will be created at the chosen path.
|
||||
|
||||
Returns `String | undefined`, the path of the file chosen by the user; if the dialog is cancelled it returns `undefined`.
|
||||
@@ -193,8 +202,14 @@ The `filters` specifies an array of file types that can be displayed, see
|
||||
* `message` String (optional) _macOS_ - Message to display above text fields.
|
||||
* `nameFieldLabel` String (optional) _macOS_ - Custom label for the text
|
||||
displayed in front of the filename text field.
|
||||
* `showsTagField` Boolean (optional) _macOS_ - Show the tags input box,
|
||||
defaults to `true`.
|
||||
* `showsTagField` Boolean (optional) _macOS_ - Show the tags input box, defaults to `true`.
|
||||
* `properties` String[] (optional)
|
||||
* `showHiddenFiles` - Show hidden files in dialog.
|
||||
* `createDirectory` _macOS_ - Allow creating new directories from dialog.
|
||||
* `treatPackageAsDirectory` _macOS_ - Treat packages, such as `.app` folders,
|
||||
as a directory instead of a file.
|
||||
* `showOverwriteConfirmation` _Linux_ - Sets whether the user will be presented a confirmation dialog if the user types a file name that already exists.
|
||||
* `dontAddToRecent` _Windows_ - Do not add the item being saved to the recent documents list.
|
||||
* `securityScopedBookmarks` Boolean (optional) _macOS_ _mas_ - Create a [security scoped bookmark](https://developer.apple.com/library/content/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW16) when packaged for the Mac App Store. If this option is enabled and the file doesn't already exist a blank file will be created at the chosen path.
|
||||
|
||||
Returns `Promise<Object>` - Resolve with an object containing the following:
|
||||
|
||||
@@ -77,7 +77,6 @@ only the next time a message is sent to `channel`, after which it is removed.
|
||||
|
||||
* `channel` String
|
||||
* `listener` Function
|
||||
* `...args` any[]
|
||||
|
||||
Removes the specified `listener` from the listener array for the specified
|
||||
`channel`.
|
||||
@@ -148,4 +147,4 @@ found in the [`ipc-main-invoke-event`](structures/ipc-main-invoke-event.md)
|
||||
structure docs.
|
||||
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[web-contents-send]: web-contents.md#contentssendchannel-args
|
||||
[web-contents-send]: web-contents.md#contentssendchannel-arg1-arg2-
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
The Electron team is currently undergoing an initiative to convert callback-based functions in Electron to return Promises. During this transition period, both the callback and Promise-based versions of these functions will work correctly, and will both be documented.
|
||||
|
||||
To enable deprecation warnings for these updated functions, use the `process.enablePromiseAPI` runtime flag.
|
||||
To enable deprecation warnings for these updated functions, use the [`process.enablePromiseAPIs` runtime flag](../process.md#processenablepromiseapis).
|
||||
|
||||
When a majority of affected functions are migrated, this flag will be enabled by default and all developers will be able to see these deprecation warnings. At that time, the callback-based versions will also be removed from documentation. This document will be continuously updated as more functions are converted.
|
||||
|
||||
|
||||
@@ -14,11 +14,11 @@ image file path as a `String`:
|
||||
const { BrowserWindow, Tray } = require('electron')
|
||||
|
||||
const appIcon = new Tray('/Users/somebody/images/icon.png')
|
||||
let win = new BrowserWindow({ icon: '/Users/somebody/images/window.png' })
|
||||
const win = new BrowserWindow({ icon: '/Users/somebody/images/window.png' })
|
||||
console.log(appIcon, win)
|
||||
```
|
||||
|
||||
Or read the image from the clipboard which returns a `NativeImage`:
|
||||
Or read the image from the clipboard, which returns a `NativeImage`:
|
||||
|
||||
```javascript
|
||||
const { clipboard, Tray } = require('electron')
|
||||
@@ -33,19 +33,19 @@ Currently `PNG` and `JPEG` image formats are supported. `PNG` is recommended
|
||||
because of its support for transparency and lossless compression.
|
||||
|
||||
On Windows, you can also load `ICO` icons from file paths. For best visual
|
||||
quality it is recommended to include at least the following sizes in the:
|
||||
quality, it is recommended to include at least the following sizes in the:
|
||||
|
||||
* Small icon
|
||||
* 16x16 (100% DPI scale)
|
||||
* 20x20 (125% DPI scale)
|
||||
* 24x24 (150% DPI scale)
|
||||
* 32x32 (200% DPI scale)
|
||||
* 16x16 (100% DPI scale)
|
||||
* 20x20 (125% DPI scale)
|
||||
* 24x24 (150% DPI scale)
|
||||
* 32x32 (200% DPI scale)
|
||||
* Large icon
|
||||
* 32x32 (100% DPI scale)
|
||||
* 40x40 (125% DPI scale)
|
||||
* 48x48 (150% DPI scale)
|
||||
* 64x64 (200% DPI scale)
|
||||
* 256x256
|
||||
* 32x32 (100% DPI scale)
|
||||
* 40x40 (125% DPI scale)
|
||||
* 48x48 (150% DPI scale)
|
||||
* 64x64 (200% DPI scale)
|
||||
* 256x256
|
||||
|
||||
Check the *Size requirements* section in [this article][icons].
|
||||
|
||||
@@ -56,7 +56,7 @@ Check the *Size requirements* section in [this article][icons].
|
||||
On platforms that have high-DPI support such as Apple Retina displays, you can
|
||||
append `@2x` after image's base filename to mark it as a high resolution image.
|
||||
|
||||
For example if `icon.png` is a normal image that has standard resolution, then
|
||||
For example, if `icon.png` is a normal image that has standard resolution, then
|
||||
`icon@2x.png` will be treated as a high resolution image that has double DPI
|
||||
density.
|
||||
|
||||
@@ -73,11 +73,11 @@ images/
|
||||
|
||||
```javascript
|
||||
const { Tray } = require('electron')
|
||||
let appIcon = new Tray('/Users/somebody/images/icon.png')
|
||||
const appIcon = new Tray('/Users/somebody/images/icon.png')
|
||||
console.log(appIcon)
|
||||
```
|
||||
|
||||
Following suffixes for DPI are also supported:
|
||||
The following suffixes for DPI are also supported:
|
||||
|
||||
* `@1x`
|
||||
* `@1.25x`
|
||||
@@ -97,7 +97,7 @@ Template images consist of black and an alpha channel.
|
||||
Template images are not intended to be used as standalone images and are usually
|
||||
mixed with other content to create the desired final appearance.
|
||||
|
||||
The most common case is to use template images for a menu bar icon so it can
|
||||
The most common case is to use template images for a menu bar icon, so it can
|
||||
adapt to both light and dark menu bars.
|
||||
|
||||
**Note:** Template image is only supported on macOS.
|
||||
@@ -132,7 +132,7 @@ a valid image.
|
||||
```javascript
|
||||
const nativeImage = require('electron').nativeImage
|
||||
|
||||
let image = nativeImage.createFromPath('/Users/somebody/images/icon.png')
|
||||
const image = nativeImage.createFromPath('/Users/somebody/images/icon.png')
|
||||
console.log(image)
|
||||
```
|
||||
|
||||
@@ -180,7 +180,8 @@ Creates a new `NativeImage` instance from the NSImage that maps to the
|
||||
given image name. See [`System Icons`](https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/system-icons/)
|
||||
for a list of possible values.
|
||||
|
||||
The `hslShift` is applied to the image with the following rules
|
||||
The `hslShift` is applied to the image with the following rules:
|
||||
|
||||
* `hsl_shift[0]` (hue): The absolute hue value for the image - 0 and 1 map
|
||||
to 0 and 360 on the hue color wheel (red).
|
||||
* `hsl_shift[1]` (saturation): A saturation shift for the image, with the
|
||||
@@ -248,9 +249,9 @@ Returns `String` - The data URL of the image.
|
||||
|
||||
Returns `Buffer` - A [Buffer][buffer] that contains the image's raw bitmap pixel data.
|
||||
|
||||
The difference between `getBitmap()` and `toBitmap()` is, `getBitmap()` does not
|
||||
The difference between `getBitmap()` and `toBitmap()` is that `getBitmap()` does not
|
||||
copy the bitmap data, so you have to use the returned Buffer immediately in
|
||||
current event loop tick, otherwise the data might be changed or destroyed.
|
||||
current event loop tick; otherwise the data might be changed or destroyed.
|
||||
|
||||
#### `image.getNativeHandle()` _macOS_
|
||||
|
||||
@@ -295,7 +296,7 @@ Returns `NativeImage` - The cropped image.
|
||||
* `width` Integer (optional) - Defaults to the image's width.
|
||||
* `height` Integer (optional) - Defaults to the image's height.
|
||||
* `quality` String (optional) - The desired quality of the resize image.
|
||||
Possible values are `good`, `better` or `best`. The default is `best`.
|
||||
Possible values are `good`, `better`, or `best`. The default is `best`.
|
||||
These values express a desired quality/speed tradeoff. They are translated
|
||||
into an algorithm-specific method that depends on the capabilities
|
||||
(CPU, GPU) of the underlying platform. It is possible for all three methods
|
||||
@@ -328,9 +329,9 @@ can be called on empty images.
|
||||
|
||||
[buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer
|
||||
|
||||
### Instance Properties
|
||||
## Properties
|
||||
|
||||
#### `nativeImage.isMacTemplateImage` _macOS_
|
||||
### `nativeImage.isMacTemplateImage` _macOS_
|
||||
|
||||
A `Boolean` property that determines whether the image is considered a [template image](https://developer.apple.com/documentation/appkit/nsimage/1520017-template).
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ app.on('ready', async () => {
|
||||
})
|
||||
```
|
||||
|
||||
See [`--log-net-log`](chrome-command-line-switches.md#--log-net-logpath) to log network events throughout the app's lifecycle.
|
||||
See [`--log-net-log`](command-line-switches.md#--log-net-logpath) to log network events throughout the app's lifecycle.
|
||||
|
||||
**Note:** All methods unless specified can only be used after the `ready` event
|
||||
of the `app` module gets emitted.
|
||||
|
||||
@@ -35,8 +35,10 @@ Returns `Boolean` - Whether or not desktop notifications are supported on the cu
|
||||
* `silent` Boolean (optional) - Whether or not to emit an OS notification noise when showing the notification.
|
||||
* `icon` (String | [NativeImage](native-image.md)) (optional) - An icon to use in the notification.
|
||||
* `hasReply` Boolean (optional) _macOS_ - Whether or not to add an inline reply option to the notification.
|
||||
* `timeoutType` String (optional) _Linux_ _Windows_ - The timeout duration of the notification. Can be 'default' or 'never'.
|
||||
* `replyPlaceholder` String (optional) _macOS_ - The placeholder to write in the inline reply input field.
|
||||
* `sound` String (optional) _macOS_ - The name of the sound file to play when the notification is shown.
|
||||
* `urgency` String (optional) _Linux_ - The urgency level of the notification. Can be 'normal', 'critical', or 'low'.
|
||||
* `actions` [NotificationAction[]](structures/notification-action.md) (optional) _macOS_ - Actions to add to the notification. Please read the available actions and limitations in the `NotificationAction` documentation.
|
||||
* `closeButtonText` String (optional) _macOS_ - A custom title for the close button of an alert. An empty string will cause the default localized text to be used.
|
||||
|
||||
@@ -144,6 +146,18 @@ A `Boolean` property representing whether the notification is silent.
|
||||
|
||||
A `Boolean` property representing whether the notification has a reply action.
|
||||
|
||||
#### `notification.urgency` _Linux_
|
||||
|
||||
A `String` property representing the urgency level of the notification. Can be 'normal', 'critical', or 'low'.
|
||||
|
||||
Default is 'low' - see [NotifyUrgency](https://developer.gnome.org/notification-spec/#urgency-levels) for more information.
|
||||
|
||||
#### `notification.timeoutType` _Linux_ _Windows_
|
||||
|
||||
A `String` property representing the type of timeout duration for the notification. Can be 'default' or 'never'.
|
||||
|
||||
If `timeoutType` is set to 'never', the notification never expires. It stays open until closed by the calling API or the user.
|
||||
|
||||
#### `notification.actions`
|
||||
|
||||
A [`NotificationAction[]`](structures/notification-action.md) property representing the actions of the notification.
|
||||
|
||||
@@ -217,15 +217,11 @@ that all statistics are reported in Kilobytes.
|
||||
|
||||
Returns `String` - The version of the host operating system.
|
||||
|
||||
Example:
|
||||
Examples:
|
||||
|
||||
```js
|
||||
const version = process.getSystemVersion()
|
||||
console.log(version)
|
||||
// On macOS -> '10.13.6'
|
||||
// On Windows -> '10.0.17763'
|
||||
// On Linux -> '4.15.0-45-generic'
|
||||
```
|
||||
* `macOS` -> `10.13.6`
|
||||
* `Windows` -> `10.0.17763`
|
||||
* `Linux` -> `4.15.0-45-generic`
|
||||
|
||||
**Note:** It returns the actual operating system version instead of kernel version on macOS unlike `os.release()`.
|
||||
|
||||
|
||||
@@ -389,7 +389,9 @@ which sends a `Buffer` as a response.
|
||||
* `url` String
|
||||
* `method` String (optional)
|
||||
* `session` Session | null (optional)
|
||||
* `uploadData` [ProtocolResponseUploadData](structures/protocol-response-upload-data.md) (optional)
|
||||
* `uploadData` Object (optional)
|
||||
* `contentType` String - MIME type of the content.
|
||||
* `data` String - Content to be sent.
|
||||
* `completion` Function (optional)
|
||||
* `error` Error
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ session.defaultSession.on('will-download', (event, item, webContents) => {
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'preconnect' _Experimental_
|
||||
#### Event: 'preconnect'
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -139,9 +139,9 @@ Writes any unwritten DOMStorage data to disk.
|
||||
#### `ses.setProxy(config)`
|
||||
|
||||
* `config` Object
|
||||
* `pacScript` String - The URL associated with the PAC file.
|
||||
* `proxyRules` String - Rules indicating which proxies to use.
|
||||
* `proxyBypassRules` String - Rules indicating which URLs should
|
||||
* `pacScript` String (optional) - The URL associated with the PAC file.
|
||||
* `proxyRules` String (optional) - Rules indicating which proxies to use.
|
||||
* `proxyBypassRules` String (optional) - Rules indicating which URLs should
|
||||
bypass the proxy settings.
|
||||
|
||||
Returns `Promise<void>` - Resolves when the proxy setting process is complete.
|
||||
@@ -252,7 +252,7 @@ window.webContents.session.enableNetworkEmulation({
|
||||
window.webContents.session.enableNetworkEmulation({ offline: true })
|
||||
```
|
||||
|
||||
#### `ses.preconnect(options)` _Experimental_
|
||||
#### `ses.preconnect(options)`
|
||||
|
||||
* `options` Object
|
||||
* `url` String - URL for preconnect. Only the origin is relevant for opening the socket.
|
||||
@@ -267,7 +267,7 @@ the original network configuration.
|
||||
|
||||
#### `ses.setCertificateVerifyProc(proc)`
|
||||
|
||||
* `proc` Function
|
||||
* `proc` Function | null
|
||||
* `request` Object
|
||||
* `hostname` String
|
||||
* `certificate` [Certificate](structures/certificate.md)
|
||||
@@ -408,6 +408,17 @@ Returns `String` - The user agent for this session.
|
||||
|
||||
Returns `Promise<Buffer>` - resolves with blob data.
|
||||
|
||||
#### `ses.downloadURL(url)`
|
||||
|
||||
* `url` String
|
||||
|
||||
Initiates a download of the resource at `url`.
|
||||
The API will generate a [DownloadItem](download-item.md) that can be accessed
|
||||
with the [will-download](#event-will-download) event.
|
||||
|
||||
**Note:** This does not perform any security checks that relate to a page's origin,
|
||||
unlike [`webContents.downloadURL`](web-contents.md#contentsdownloadurlurl).
|
||||
|
||||
#### `ses.createInterruptedDownload(options)`
|
||||
|
||||
* `options` Object
|
||||
@@ -416,8 +427,8 @@ Returns `Promise<Buffer>` - resolves with blob data.
|
||||
* `mimeType` String (optional)
|
||||
* `offset` Integer - Start range for the download.
|
||||
* `length` Integer - Total length of the download.
|
||||
* `lastModified` String - Last-Modified header value.
|
||||
* `eTag` String - ETag header value.
|
||||
* `lastModified` String (optional) - Last-Modified header value.
|
||||
* `eTag` String (optional) - ETag header value.
|
||||
* `startTime` Double (optional) - Time when download was started in
|
||||
number of seconds since UNIX epoch.
|
||||
|
||||
|
||||
@@ -43,11 +43,12 @@ Returns `Promise<void>`
|
||||
|
||||
Open the given external protocol URL in the desktop's default manner. (For example, mailto: URLs in the user's default mail agent).
|
||||
|
||||
### `shell.moveItemToTrash(fullPath)`
|
||||
### `shell.moveItemToTrash(fullPath[, deleteOnFail])`
|
||||
|
||||
* `fullPath` String
|
||||
* `deleteOnFail` Boolean (optional) - Whether or not to unilaterally remove the item if the Trash is disabled or unsupported on the volume. _macOS_
|
||||
|
||||
Returns `Boolean` - Whether the item was successfully moved to the trash.
|
||||
Returns `Boolean` - Whether the item was successfully moved to the trash or otherwise deleted.
|
||||
|
||||
Move the given file to trash and returns a boolean status for the operation.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# InputEvent Object
|
||||
|
||||
* `modifiers` String[] - An array of modifiers of the event, can
|
||||
be `shift`, `control`, `alt`, `meta`, `isKeypad`, `isAutoRepeat`,
|
||||
`leftButtonDown`, `middleButtonDown`, `rightButtonDown`, `capsLock`,
|
||||
`numLock`, `left`, `right`.
|
||||
* `modifiers` String[] (optional) - An array of modifiers of the event, can
|
||||
be `shift`, `control`, `ctrl`, `alt`, `meta`, `command`, `cmd`, `isKeypad`,
|
||||
`isAutoRepeat`, `leftButtonDown`, `middleButtonDown`, `rightButtonDown`,
|
||||
`capsLock`, `numLock`, `left`, `right`.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# ProtocolResponseUploadData Object
|
||||
|
||||
* `contentType` String - MIME type of the content.
|
||||
* `data` String | Buffer - Content to be sent.
|
||||
* `data` String - Content to be sent.
|
||||
|
||||
4
docs/api/structures/shared-worker-info.md
Normal file
4
docs/api/structures/shared-worker-info.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# SharedWorkerInfo Object
|
||||
|
||||
* `id` String - The unique id of the shared worker.
|
||||
* `url` String - The url of the shared worker.
|
||||
@@ -8,16 +8,23 @@ Process: [Main](../tutorial/application-architecture.md#main-and-renderer-proces
|
||||
|
||||
* `options` Object
|
||||
* `label` String (optional) - Button text.
|
||||
* `accessibilityLabel` String (optional) - A short description of the button for use by screenreaders like VoiceOver.
|
||||
* `backgroundColor` String (optional) - Button background color in hex format,
|
||||
i.e `#ABCDEF`.
|
||||
* `icon` [NativeImage](native-image.md) | String (optional) - Button icon.
|
||||
* `iconPosition` String (optional) - Can be `left`, `right` or `overlay`.
|
||||
* `iconPosition` String (optional) - Can be `left`, `right` or `overlay`. Defaults to `overlay`.
|
||||
* `click` Function (optional) - Function to call when the button is clicked.
|
||||
|
||||
When defining `accessibilityLabel`, ensure you have considered macOS [best practices](https://developer.apple.com/documentation/appkit/nsaccessibilitybutton/1524910-accessibilitylabel?language=objc).
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `TouchBarButton`:
|
||||
|
||||
#### `touchBarButton.accessibilityLabel`
|
||||
|
||||
A `String` representing the description of the button to be read by a screen reader. Will only be read by screen readers if no label is set.
|
||||
|
||||
#### `touchBarButton.label`
|
||||
|
||||
A `String` representing the button's current text. Changing this value immediately updates the button
|
||||
|
||||
@@ -8,8 +8,11 @@ Process: [Main](../tutorial/application-architecture.md#main-and-renderer-proces
|
||||
|
||||
* `options` Object
|
||||
* `label` String (optional) - Text to display.
|
||||
* `accessibilityLabel` String (optional) - A short description of the button for use by screenreaders like VoiceOver.
|
||||
* `textColor` String (optional) - Hex color of text, i.e `#ABCDEF`.
|
||||
|
||||
When defining `accessibilityLabel`, ensure you have considered macOS [best practices](https://developer.apple.com/documentation/appkit/nsaccessibilitybutton/1524910-accessibilitylabel?language=objc).
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `TouchBarLabel`:
|
||||
@@ -19,6 +22,10 @@ The following properties are available on instances of `TouchBarLabel`:
|
||||
A `String` representing the label's current text. Changing this value immediately updates the label in
|
||||
the touch bar.
|
||||
|
||||
#### `touchBarLabel.accessibilityLabel`
|
||||
|
||||
A `String` representing the description of the label to be read by a screen reader.
|
||||
|
||||
#### `touchBarLabel.textColor`
|
||||
|
||||
A `String` hex code representing the label's current text color. Changing this value immediately updates the
|
||||
|
||||
@@ -9,7 +9,7 @@ Process: [Main](../tutorial/application-architecture.md#main-and-renderer-proces
|
||||
* `options` Object
|
||||
* `label` String (optional) - Popover button text.
|
||||
* `icon` [NativeImage](native-image.md) (optional) - Popover button icon.
|
||||
* `items` [TouchBar](touch-bar.md) (optional) - Items to display in the popover.
|
||||
* `items` [TouchBar](touch-bar.md) - Items to display in the popover.
|
||||
* `showCloseButton` Boolean (optional) - `true` to display a close button
|
||||
on the left of the popover, `false` to not show it. Default is `true`.
|
||||
|
||||
|
||||
@@ -12,10 +12,10 @@ Process: [Main](../tutorial/application-architecture.md#main-and-renderer-proces
|
||||
* `selectedIndex` Integer - The index of the item the user selected.
|
||||
* `highlight` Function (optional) - Called when the user taps any item.
|
||||
* `highlightedIndex` Integer - The index of the item the user touched.
|
||||
* `selectedStyle` String (optional) - Selected item style. Defaults to `null`.
|
||||
* `overlayStyle` String (optional) - Selected overlay item style. Defaults to `null`.
|
||||
* `selectedStyle` String (optional) - Selected item style. Can be `background`, `outline` or `none`. Defaults to `none`.
|
||||
* `overlayStyle` String (optional) - Selected overlay item style. Can be `background`, `outline` or `none`. Defaults to `none`.
|
||||
* `showArrowButtons` Boolean (optional) - Defaults to `false`.
|
||||
* `mode` String (optional) - Defaults to `free`.
|
||||
* `mode` String (optional) - Can be `fixed` or `free`. The default is `free`.
|
||||
* `continuous` Boolean (optional) - Defaults to `true`.
|
||||
|
||||
### Instance Properties
|
||||
@@ -34,7 +34,7 @@ updates the control in the touch bar. Possible values:
|
||||
|
||||
* `background` - Maps to `[NSScrubberSelectionStyle roundedBackgroundStyle]`.
|
||||
* `outline` - Maps to `[NSScrubberSelectionStyle outlineOverlayStyle]`.
|
||||
* `null` - Actually null, not a string, removes all styles.
|
||||
* `none` - Removes all styles.
|
||||
|
||||
#### `touchBarScrubber.overlayStyle`
|
||||
|
||||
@@ -44,7 +44,7 @@ touch bar. Possible values:
|
||||
|
||||
* `background` - Maps to `[NSScrubberSelectionStyle roundedBackgroundStyle]`.
|
||||
* `outline` - Maps to `[NSScrubberSelectionStyle outlineOverlayStyle]`.
|
||||
* `null` - Actually null, not a string, removes all styles.
|
||||
* `none` - Removes all styles.
|
||||
|
||||
#### `touchBarScrubber.showArrowButtons`
|
||||
|
||||
|
||||
@@ -10,23 +10,23 @@ Process: [Main](../tutorial/application-architecture.md#main-and-renderer-proces
|
||||
* `segmentStyle` String (optional) - Style of the segments:
|
||||
* `automatic` - Default. The appearance of the segmented control is
|
||||
automatically determined based on the type of window in which the control
|
||||
is displayed and the position within the window.
|
||||
* `rounded` - The control is displayed using the rounded style.
|
||||
is displayed and the position within the window. Maps to `NSSegmentStyleAutomatic`.
|
||||
* `rounded` - The control is displayed using the rounded style. Maps to `NSSegmentStyleRounded`.
|
||||
* `textured-rounded` - The control is displayed using the textured rounded
|
||||
style.
|
||||
* `round-rect` - The control is displayed using the round rect style.
|
||||
style. Maps to `NSSegmentStyleTexturedRounded`.
|
||||
* `round-rect` - The control is displayed using the round rect style. Maps to `NSSegmentStyleRoundRect`.
|
||||
* `textured-square` - The control is displayed using the textured square
|
||||
style.
|
||||
* `capsule` - The control is displayed using the capsule style.
|
||||
* `small-square` - The control is displayed using the small square style.
|
||||
style. Maps to `NSSegmentStyleTexturedSquare`.
|
||||
* `capsule` - The control is displayed using the capsule style. Maps to `NSSegmentStyleCapsule`.
|
||||
* `small-square` - The control is displayed using the small square style. Maps to `NSSegmentStyleSmallSquare`.
|
||||
* `separated` - The segments in the control are displayed very close to each
|
||||
other but not touching.
|
||||
other but not touching. Maps to `NSSegmentStyleSeparated`.
|
||||
* `mode` String (optional) - The selection mode of the control:
|
||||
* `single` - Default. One item selected at a time, selecting one deselects the previously selected item.
|
||||
* `multiple` - Multiple items can be selected at a time.
|
||||
* `buttons` - Make the segments act as buttons, each segment can be pressed and released but never marked as active.
|
||||
* `single` - Default. One item selected at a time, selecting one deselects the previously selected item. Maps to `NSSegmentSwitchTrackingSelectOne`.
|
||||
* `multiple` - Multiple items can be selected at a time. Maps to `NSSegmentSwitchTrackingSelectAny`.
|
||||
* `buttons` - Make the segments act as buttons, each segment can be pressed and released but never marked as active. Maps to `NSSegmentSwitchTrackingMomentary`.
|
||||
* `segments` [SegmentedControlSegment[]](structures/segmented-control-segment.md) - An array of segments to place in this control.
|
||||
* `selectedIndex` Integer (optional) - The index of the currently selected segment, will update automatically with user interaction. When the mode is multiple it will be the last selected item.
|
||||
* `selectedIndex` Integer (optional) - The index of the currently selected segment, will update automatically with user interaction. When the mode is `multiple` it will be the last selected item.
|
||||
* `change` Function (optional) - Called when the user selects a new segment.
|
||||
* `selectedIndex` Integer - The index of the segment the user selected.
|
||||
* `isSelected` Boolean - Whether as a result of user selection the segment is selected or not.
|
||||
|
||||
@@ -8,6 +8,6 @@ Process: [Main](../tutorial/application-architecture.md#main-and-renderer-proces
|
||||
|
||||
* `options` Object
|
||||
* `size` String (optional) - Size of spacer, possible values are:
|
||||
* `small` - Small space between items.
|
||||
* `large` - Large space between items.
|
||||
* `flexible` - Take up all available space.
|
||||
* `small` - Small space between items. Maps to `NSTouchBarItemIdentifierFixedSpaceSmall`. This is the default.
|
||||
* `large` - Large space between items. Maps to `NSTouchBarItemIdentifierFixedSpaceLarge`.
|
||||
* `flexible` - Take up all available space. Maps to `NSTouchBarItemIdentifierFlexibleSpace`.
|
||||
|
||||
@@ -222,12 +222,31 @@ Returns `Boolean` - Whether double click events will be ignored.
|
||||
#### `tray.displayBalloon(options)` _Windows_
|
||||
|
||||
* `options` Object
|
||||
* `icon` ([NativeImage](native-image.md) | String) (optional) -
|
||||
* `icon` ([NativeImage](native-image.md) | String) (optional) - Icon to use when `iconType` is `custom`.
|
||||
* `iconType` String (optional) - Can be `none`, `info`, `warning`, `error` or `custom`. Default is `custom`.
|
||||
* `title` String
|
||||
* `content` String
|
||||
* `largeIcon` Boolean (optional) - The large version of the icon should be used. Default is `true`. Maps to [`NIIF_LARGE_ICON`][NIIF_LARGE_ICON].
|
||||
* `noSound` Boolean (optional) - Do not play the associated sound. Default is `false`. Maps to [`NIIF_NOSOUND`][NIIF_NOSOUND].
|
||||
* `respectQuietTime` Boolean (optional) - Do not display the balloon notification if the current user is in "quiet time". Default is `false`. Maps to [`NIIF_RESPECT_QUIET_TIME`][NIIF_RESPECT_QUIET_TIME].
|
||||
|
||||
Displays a tray balloon.
|
||||
|
||||
[NIIF_NOSOUND]: https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa#niif_nosound-0x00000010
|
||||
[NIIF_LARGE_ICON]: https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa#niif_large_icon-0x00000020
|
||||
[NIIF_RESPECT_QUIET_TIME]: https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa#niif_respect_quiet_time-0x00000080
|
||||
|
||||
#### `tray.removeBalloon()` _Windows_
|
||||
|
||||
Removes a tray balloon.
|
||||
|
||||
#### `tray.focus()` _Windows_
|
||||
|
||||
Returns focus to the taskbar notification area.
|
||||
Notification area icons should use this message when they have completed their UI operation.
|
||||
For example, if the icon displays a shortcut menu, but the user presses ESC to cancel it,
|
||||
use `tray.focus()` to return focus to the notification area.
|
||||
|
||||
#### `tray.popUpContextMenu([menu, position])` _macOS_ _Windows_
|
||||
|
||||
* `menu` Menu (optional)
|
||||
|
||||
@@ -454,8 +454,10 @@ The usage is the same with [the `select-client-certificate` event of
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `authenticationResponseDetails` Object
|
||||
* `request` Object
|
||||
* `method` String
|
||||
* `url` URL
|
||||
* `referrer` URL
|
||||
* `authInfo` Object
|
||||
* `isProxy` Boolean
|
||||
* `scheme` String
|
||||
@@ -463,8 +465,8 @@ Returns:
|
||||
* `port` Integer
|
||||
* `realm` String
|
||||
* `callback` Function
|
||||
* `username` String (optional)
|
||||
* `password` String (optional)
|
||||
* `username` String
|
||||
* `password` String
|
||||
|
||||
Emitted when `webContents` wants to do basic auth.
|
||||
|
||||
@@ -703,8 +705,7 @@ Returns:
|
||||
* `line` Integer
|
||||
* `sourceId` String
|
||||
|
||||
Emitted when the associated window logs a console message. Will not be emitted
|
||||
for windows with *offscreen rendering* enabled.
|
||||
Emitted when the associated window logs a console message.
|
||||
|
||||
#### Event: 'preload-error'
|
||||
|
||||
@@ -1236,7 +1237,7 @@ Captures a snapshot of the page within `rect`. Omitting `rect` will capture the
|
||||
|
||||
Get the system printer list.
|
||||
|
||||
Returns [`PrinterInfo[]`](structures/printer-info.md)
|
||||
Returns [`PrinterInfo[]`](structures/printer-info.md).
|
||||
|
||||
#### `contents.print([options], [callback])`
|
||||
|
||||
@@ -1262,6 +1263,8 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
|
||||
* `dpi` Object (optional)
|
||||
* `horizontal` Number (optional) - The horizontal dpi.
|
||||
* `vertical` Number (optional) - The vertical dpi.
|
||||
* `header` String (optional) - String to be printed as page header.
|
||||
* `footer` String (optional) - String to be printed as page footer.
|
||||
* `callback` Function (optional)
|
||||
* `success` Boolean - Indicates success of the print call.
|
||||
* `failureReason` String - Called back if the print fails; can be `cancelled` or `failed`.
|
||||
@@ -1323,13 +1326,12 @@ win.loadURL('http://github.com')
|
||||
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
// Use default printing options
|
||||
win.webContents.printToPDF({}).then(data => {
|
||||
win.webContents.printToPDF({}, (error, data) => {
|
||||
if (error) throw error
|
||||
fs.writeFile('/tmp/print.pdf', data, (error) => {
|
||||
if (error) throw error
|
||||
console.log('Write PDF successfully.')
|
||||
})
|
||||
}).catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
})
|
||||
```
|
||||
@@ -1458,6 +1460,16 @@ Starts inspecting element at position (`x`, `y`).
|
||||
|
||||
Opens the developer tools for the shared worker context.
|
||||
|
||||
#### `contents.inspectSharedWorkerById(workerId)`
|
||||
|
||||
* `workerId` String
|
||||
|
||||
Inspects the shared worker based on its ID.
|
||||
|
||||
#### `contents.getAllSharedWorkers()`
|
||||
|
||||
Returns [`SharedWorkerInfo[]`](structures/shared-worker-info.md) - Information about all Shared Workers.
|
||||
|
||||
#### `contents.inspectServiceWorker()`
|
||||
|
||||
Opens the developer tools for the service worker context.
|
||||
@@ -1590,8 +1602,8 @@ End subscribing for frame presentation events.
|
||||
|
||||
* `item` Object
|
||||
* `file` String[] | String - The path(s) to the file(s) being dragged.
|
||||
* `icon` [NativeImage](native-image.md) - The image must be non-empty on
|
||||
macOS.
|
||||
* `icon` [NativeImage](native-image.md) | String - The image must be
|
||||
non-empty on macOS.
|
||||
|
||||
Sets the `item` as dragging item for current drag-drop operation, `file` is the
|
||||
absolute path of the file to be dragged, and `icon` is the image showing under
|
||||
|
||||
@@ -146,7 +146,7 @@ response are visible by the time this listener is fired.
|
||||
* `timestamp` Double
|
||||
* `statusLine` String
|
||||
* `statusCode` Integer
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `responseHeaders` Record<string, string> (optional)
|
||||
* `callback` Function
|
||||
* `headersReceivedResponse` Object
|
||||
* `cancel` Boolean (optional)
|
||||
@@ -175,7 +175,7 @@ The `callback` has to be called with a `response` object.
|
||||
* `resourceType` String
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `responseHeaders` Record<string, string> (optional)
|
||||
* `fromCache` Boolean - Indicates whether the response was fetched from disk
|
||||
cache.
|
||||
* `statusCode` Integer
|
||||
@@ -205,7 +205,7 @@ and response headers are available.
|
||||
* `ip` String (optional) - The server IP address that the request was
|
||||
actually sent to.
|
||||
* `fromCache` Boolean
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `responseHeaders` Record<string, string> (optional)
|
||||
|
||||
The `listener` will be called with `listener(details)` when a server initiated
|
||||
redirect is about to occur.
|
||||
@@ -224,7 +224,7 @@ redirect is about to occur.
|
||||
* `resourceType` String
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `responseHeaders` Record<string, string> (optional)
|
||||
* `fromCache` Boolean
|
||||
* `statusCode` Integer
|
||||
* `statusLine` String
|
||||
|
||||
@@ -72,6 +72,7 @@ origin URLs.
|
||||
$ cd src/electron
|
||||
$ git remote remove origin
|
||||
$ git remote add origin https://github.com/electron/electron
|
||||
$ git checkout master
|
||||
$ git branch --set-upstream-to=origin/master
|
||||
$ cd -
|
||||
```
|
||||
@@ -226,20 +227,9 @@ under `src/` directory.
|
||||
|
||||
```sh
|
||||
$ ninja -C out/Debug third_party/electron_node:headers
|
||||
# Install the test modules with the generated headers
|
||||
$ (cd electron/spec && npm i --nodedir=../../out/Debug/gen/node_headers)
|
||||
```
|
||||
|
||||
Then, run Electron with `electron/spec` as the argument:
|
||||
|
||||
```sh
|
||||
# on Mac:
|
||||
$ ./out/Debug/Electron.app/Contents/MacOS/Electron electron/spec
|
||||
# on Windows:
|
||||
$ ./out/Debug/electron.exe electron/spec
|
||||
# on Linux:
|
||||
$ ./out/Debug/electron electron/spec
|
||||
```
|
||||
You can now [run the tests](testing.md#unit-tests).
|
||||
|
||||
If you're debugging something, it can be helpful to pass some extra flags to
|
||||
the Electron binary:
|
||||
|
||||
@@ -5,8 +5,15 @@ Follow the guidelines below for building Electron on Windows.
|
||||
## Prerequisites
|
||||
|
||||
* Windows 10 / Server 2012 R2 or higher
|
||||
* Visual Studio 2017 15.7.2 or higher - [download VS 2017 Community Edition for
|
||||
* Visual Studio 2017 15.7.2 or higher - [download VS 2019 Community Edition for
|
||||
free](https://www.visualstudio.com/vs/)
|
||||
* See [the Chromium build documentation](https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md#visual-studio) for more details on which Visual Studio
|
||||
components are required.
|
||||
* If your Visual Studio is installed in a directory other than the default, you'll need to
|
||||
set a few environment variables to point the toolchains to your installation path.
|
||||
* `vs2019_install = DRIVE:\path\to\Microsoft Visual Studio\2019\Community`
|
||||
(replace `2019` and `Community` with your installed versions)
|
||||
* `WINDOWSSDKDIR = DRIVE:\path\to\Windows Kits\10`
|
||||
* [Python 2.7.10 or higher](http://www.python.org/download/releases/2.7/)
|
||||
* Contrary to the `depot_tools` setup instructions linked below, you will need
|
||||
to use your locally installed Python with at least version 2.7.10 (with
|
||||
@@ -113,3 +120,10 @@ This can happen during build, when Debugging Tools for Windows has been installe
|
||||
### ImportError: No module named win32file
|
||||
|
||||
Make sure you have installed `pywin32` with `pip install pywin32`.
|
||||
|
||||
### Build Scripts Hang Until Keypress
|
||||
|
||||
This bug is a "feature" of Windows' command prompt. It happens when clicking inside the prompt window with
|
||||
`QuickEdit` enabled and is intended to allow selecting and copying output text easily.
|
||||
Since each accidental click will pause the build process, you might want to disable this
|
||||
feature in the command prompt properties.
|
||||
|
||||
@@ -48,3 +48,12 @@ would run `npm run test -- -g ipc`.
|
||||
1. Push the Windows key and search for _Manage optional features_.
|
||||
1. Click _Add a feature_.
|
||||
1. Select _Japanese Supplemental Fonts_ and click _Install_.
|
||||
|
||||
|
||||
Some tests which rely on precise pixel measurements may not work correctly on
|
||||
devices with Hi-DPI screen settings due to floating point precision errors.
|
||||
To run these tests correctly, make sure the device is set to 100% scaling.
|
||||
|
||||
To configure display scaling:
|
||||
1. Push the Windows key and search for _Display settings_.
|
||||
1. Under _Scale and layout_, make sure that the device is set to 100%.
|
||||
|
||||
0
docs/fiddles/communication/two-processes/.keep
Normal file
0
docs/fiddles/communication/two-processes/.keep
Normal file
0
docs/fiddles/media/screenshot/.keep
Normal file
0
docs/fiddles/media/screenshot/.keep
Normal file
0
docs/fiddles/menus/customize-menus/.keep
Normal file
0
docs/fiddles/menus/customize-menus/.keep
Normal file
0
docs/fiddles/menus/shortcuts/.keep
Normal file
0
docs/fiddles/menus/shortcuts/.keep
Normal file
0
docs/fiddles/native-ui/dialogs/.keep
Normal file
0
docs/fiddles/native-ui/dialogs/.keep
Normal file
0
docs/fiddles/native-ui/drag-and-drop/.keep
Normal file
0
docs/fiddles/native-ui/drag-and-drop/.keep
Normal file
0
docs/fiddles/native-ui/notifications/.keep
Normal file
0
docs/fiddles/native-ui/notifications/.keep
Normal file
0
docs/fiddles/native-ui/tray/.keep
Normal file
0
docs/fiddles/native-ui/tray/.keep
Normal file
0
docs/fiddles/system/clipboard/.keep
Normal file
0
docs/fiddles/system/clipboard/.keep
Normal file
0
docs/fiddles/system/protocol-handler/.keep
Normal file
0
docs/fiddles/system/protocol-handler/.keep
Normal file
0
docs/fiddles/system/system-information/.keep
Normal file
0
docs/fiddles/system/system-information/.keep
Normal file
0
docs/fiddles/windows/crashes-and-hangs/.keep
Normal file
0
docs/fiddles/windows/crashes-and-hangs/.keep
Normal file
0
docs/fiddles/windows/manage-windows/.keep
Normal file
0
docs/fiddles/windows/manage-windows/.keep
Normal file
Binary file not shown.
|
Before Width: | Height: | Size: 868 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 MiB |
@@ -132,7 +132,7 @@ require compilation of native code before they can be used) will need to be
|
||||
compiled to be used with Electron.
|
||||
|
||||
The vast majority of Node.js modules are _not_ native. Only 400 out of the
|
||||
~650.000 modules are native. However, if you do need native modules, please
|
||||
~650,000 modules are native. However, if you do need native modules, please
|
||||
consult [this guide on how to recompile them for Electron][native-node].
|
||||
|
||||
[node-docs]: https://nodejs.org/en/docs/
|
||||
|
||||
@@ -31,8 +31,7 @@ unifies the existing (and well maintained) build tools for Electron development
|
||||
into a cohesive package so that anyone can jump right in to Electron
|
||||
development.
|
||||
|
||||
Forge comes with [ready-to-use templates](https://electronforge.io/templates) for popular
|
||||
frameworks like React, Vue, or Angular. It uses the same core modules used by the
|
||||
Forge comes with [a ready-to-use template](https://electronforge.io/templates) using Webpack as a bundler. It includes an example typescript configuration and provides two configuration files to enable easy customization. It uses the same core modules used by the
|
||||
greater Electron community (like [`electron-packager`](https://github.com/electron/electron-packager)) –
|
||||
changes made by Electron maintainers (like Slack) benefit Forge's users, too.
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ $ code electron-quick-start
|
||||
"name": "Debug Main Process",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
|
||||
"windows": {
|
||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
|
||||
},
|
||||
"args" : ["."],
|
||||
"outputCapture": "std"
|
||||
|
||||
@@ -195,6 +195,8 @@ Finally the `index.html` is the web page you want to show:
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<!-- https://electronjs.org/docs/tutorial/security#csp-meta-tag -->
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
|
||||
@@ -38,15 +38,11 @@ npm install --platform=win32 electron
|
||||
|
||||
## Proxies
|
||||
|
||||
If you need to use an HTTP proxy, you need to set the `ELECTRON_GET_USE_PROXY` variable to any
|
||||
value, plus additional environment variables depending on your host system's Node version:
|
||||
|
||||
* [Node 10 and above][proxy-env-10]
|
||||
* [Before Node 10][proxy-env]
|
||||
If you need to use an HTTP proxy you can [set these environment variables][proxy-env].
|
||||
|
||||
## Custom Mirrors and Caches
|
||||
During installation, the `electron` module will call out to
|
||||
[`@electron/get`][electron-get] to download prebuilt binaries of
|
||||
[`electron-download`][electron-download] to download prebuilt binaries of
|
||||
Electron for your platform. It will do so by contacting GitHub's
|
||||
release download page (`https://github.com/electron/electron/releases/tag/v$VERSION`,
|
||||
where `$VERSION` is the exact version of Electron).
|
||||
@@ -56,7 +52,7 @@ can do so by either providing a mirror or an existing cache directory.
|
||||
|
||||
#### Mirror
|
||||
You can use environment variables to override the base URL, the path at which to
|
||||
look for Electron binaries, and the binary filename. The url used by `@electron/get`
|
||||
look for Electron binaries, and the binary filename. The url used by `electron-download`
|
||||
is composed as follows:
|
||||
|
||||
```plaintext
|
||||
@@ -66,11 +62,11 @@ url = ELECTRON_MIRROR + ELECTRON_CUSTOM_DIR + '/' + ELECTRON_CUSTOM_FILENAME
|
||||
For instance, to use the China mirror:
|
||||
|
||||
```plaintext
|
||||
ELECTRON_MIRROR="https://cdn.npm.taobao.org/dist/electron/"
|
||||
ELECTRON_MIRROR="https://npm.taobao.org/mirrors/electron/"
|
||||
```
|
||||
|
||||
#### Cache
|
||||
Alternatively, you can override the local cache. `@electron/get` will cache
|
||||
Alternatively, you can override the local cache. `electron-download` will cache
|
||||
downloaded binaries in a local directory to not stress your network. You can use
|
||||
that cache folder to provide custom builds of Electron or to avoid making contact
|
||||
with the network at all.
|
||||
@@ -89,26 +85,16 @@ The cache contains the version's official zip file as well as a checksum, stored
|
||||
a text file. A typical cache might look like this:
|
||||
|
||||
```sh
|
||||
├── httpsgithub.comelectronelectronreleasesdownloadv1.7.9electron-v1.7.9-darwin-x64.zip
|
||||
│ └── electron-v1.7.9-darwin-x64.zip
|
||||
├── httpsgithub.comelectronelectronreleasesdownloadv1.7.9SHASUMS256.txt
|
||||
│ └── SHASUMS256.txt
|
||||
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.1electron-v1.8.1-darwin-x64.zip
|
||||
│ └── electron-v1.8.1-darwin-x64.zip
|
||||
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.1SHASUMS256.txt
|
||||
│ └── SHASUMS256.txt
|
||||
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.1electron-v1.8.2-beta.1-darwin-x64.zip
|
||||
│ └── electron-v1.8.2-beta.1-darwin-x64.zip
|
||||
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.1SHASUMS256.txt
|
||||
│ └── SHASUMS256.txt
|
||||
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.2electron-v1.8.2-beta.2-darwin-x64.zip
|
||||
│ └── electron-v1.8.2-beta.2-darwin-x64.zip
|
||||
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.2SHASUMS256.txt
|
||||
│ └── SHASUMS256.txt
|
||||
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.3electron-v1.8.2-beta.3-darwin-x64.zip
|
||||
│ └── electron-v1.8.2-beta.3-darwin-x64.zip
|
||||
└── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.3SHASUMS256.txt
|
||||
└── SHASUMS256.txt
|
||||
├── electron-v1.7.9-darwin-x64.zip
|
||||
├── electron-v1.8.1-darwin-x64.zip
|
||||
├── electron-v1.8.2-beta.1-darwin-x64.zip
|
||||
├── electron-v1.8.2-beta.2-darwin-x64.zip
|
||||
├── electron-v1.8.2-beta.3-darwin-x64.zip
|
||||
├── SHASUMS256.txt-1.7.9
|
||||
├── SHASUMS256.txt-1.8.1
|
||||
├── SHASUMS256.txt-1.8.2-beta.1
|
||||
├── SHASUMS256.txt-1.8.2-beta.2
|
||||
├── SHASUMS256.txt-1.8.2-beta.3
|
||||
```
|
||||
|
||||
## Skip binary download
|
||||
@@ -160,8 +146,7 @@ If you need to force a re-download of the asset and the SHASUM file set the
|
||||
[npm]: https://docs.npmjs.com
|
||||
[versioning]: ./electron-versioning.md
|
||||
[releases]: https://github.com/electron/electron/releases
|
||||
[proxy-env-10]: https://github.com/gajus/global-agent/blob/v2.1.5/README.md#environment-variables
|
||||
[proxy-env]: https://github.com/np-maintain/global-tunnel/blob/v2.7.1/README.md#auto-config
|
||||
[electron-get]: https://github.com/electron/get
|
||||
[proxy-env]: https://github.com/request/request/tree/f0c4ec061141051988d1216c24936ad2e7d5c45d#controlling-proxy-behaviour-using-environment-variables
|
||||
[electron-download]: https://github.com/electron-userland/electron-download
|
||||
[npm-permissions]: https://docs.npmjs.com/getting-started/fixing-npm-permissions
|
||||
[unsafe-perm]: https://docs.npmjs.com/misc/config#unsafe-perm
|
||||
|
||||
@@ -1,431 +0,0 @@
|
||||
# Performance
|
||||
|
||||
Developers frequently ask about strategies to optimize the performance of
|
||||
Electron applications. Software engineers, consumers, and framework developers
|
||||
do not always agree on one single definition of what "performance" means. This
|
||||
document outlines some of the Electron maintainers' favorite ways to reduce the
|
||||
amount of memory, CPU, and disk resources being used while ensuring that your
|
||||
app is responsive to user input and completes operations as quickly as
|
||||
possible. Furthermore, we want all performance strategies to maintain a high
|
||||
standard for your app's security.
|
||||
|
||||
Wisdom and information about how to build performant websites with JavaScript
|
||||
generally applies to Electron apps, too. To a certain extent, resources
|
||||
discussing how to build performant Node.js applications also apply, but be
|
||||
careful to understand that the term "performance" means different things for
|
||||
a Node.js backend than it does for an application running on a client.
|
||||
|
||||
This list is provided for your convenience – and is, much like our
|
||||
[security checklist][security] – not meant to exhaustive. It is probably possible
|
||||
to build a slow Electron app that follows all the steps outlined below. Electron
|
||||
is a powerful development platform that enables you, the developer, to do more
|
||||
or less whatever you want. All that freedom means that performance is largely
|
||||
your responsibility.
|
||||
|
||||
## Measure, Measure, Measure
|
||||
|
||||
The list below contains a number of steps that are fairly straightforward and
|
||||
easy to implement. However, building the most performant version of your app
|
||||
will require you to go beyond a number of steps. Instead, you will have to
|
||||
closely examine all the code running in your app by carefully profiling and
|
||||
measuring. Where are the bottlenecks? When the user clicks a button, what
|
||||
operations take up the brunt of the time? While the app is simply idling, which
|
||||
objects take up the most memory?
|
||||
|
||||
Time and time again, we have seen that the most successful strategy for building
|
||||
a performant Electron app is to profile the running code, find the most
|
||||
resource-hungry piece of it, and to optimize it. Repeating this seemingly
|
||||
laborious process over and over again will dramatically increase your app's
|
||||
performance. Experience from working with major apps like Visual Studio Code or
|
||||
Slack has shown that this practice is by far the most reliable strategy to
|
||||
improve performance.
|
||||
|
||||
To learn more about how to profile your app's code, familiarize yourself with
|
||||
the Chrome Developer Tools. For advanced analysis looking at multiple processes
|
||||
at once, consider the [Chrome Tracing] tool.
|
||||
|
||||
### Recommended Reading
|
||||
|
||||
* [Get Started With Analyzing Runtime Performance][chrome-devtools-tutorial]
|
||||
* [Talk: "Visual Studio Code - The First Second"][vscode-first-second]
|
||||
|
||||
## Checklist
|
||||
|
||||
Chances are that your app could be a little leaner, faster, and generally less
|
||||
resource-hungry if you attempt these steps.
|
||||
|
||||
1. [Carelessly including modules](#1-carelessly-including-modules)
|
||||
2. [Loading and running code too soon](#2-loading-and-running-code-too-soon)
|
||||
3. [Blocking the main process](#3-blocking-the-main-process)
|
||||
4. [Blocking the renderer process](#4-blocking-the-renderer-process)
|
||||
5. [Unnecessary polyfills](#5-unnecessary-polyfills)
|
||||
6. [Unnecessary or blocking network requests](#6-unnecessary-or-blocking-network-requests)
|
||||
7. [Bundle your code](#7-bundle-your-code)
|
||||
|
||||
## 1) Carelessly including modules
|
||||
|
||||
Before adding a Node.js module to your application, examine said module. How
|
||||
many dependencies does that module include? What kind of resources does
|
||||
it need to simply be called in a `require()` statement? You might find
|
||||
that the module with the most downloads on the NPM package registry or the most stars on GitHub
|
||||
is not in fact the leanest or smallest one available.
|
||||
|
||||
### Why?
|
||||
|
||||
The reasoning behind this recommendation is best illustrated with a real-world
|
||||
example. During the early days of Electron, reliable detection of network
|
||||
connectivity was a problem, resulting many apps to use a module that exposed a
|
||||
simple `isOnline()` method.
|
||||
|
||||
That module detected your network connectivity by attempting to reach out to a
|
||||
number of well-known endpoints. For the list of those endpoints, it depended on
|
||||
a different module, which also contained a list of well-known ports. This
|
||||
dependency itself relied on a module containing information about ports, which
|
||||
came in the form of a JSON file with more than 100,000 lines of content.
|
||||
Whenever the module was loaded (usually in a `require('module')` statement),
|
||||
it would load all its dependencies and eventually read and parse this JSON
|
||||
file. Parsing many thousands lines of JSON is a very expensive operation. On
|
||||
a slow machine it can take up whole seconds of time.
|
||||
|
||||
In many server contexts, startup time is virtually irrelevant. A Node.js server
|
||||
that requires information about all ports is likely actually "more performant"
|
||||
if it loads all required information into memory whenever the server boots at
|
||||
the benefit of serving requests faster. The module discussed in this example is
|
||||
not a "bad" module. Electron apps, however, should not be loading, parsing, and
|
||||
storing in memory information that it does not actually need.
|
||||
|
||||
In short, a seemingly excellent module written primarily for Node.js servers
|
||||
running Linux might be bad news for your app's performance. In this particular
|
||||
example, the correct solution was to use no module at all, and to instead use
|
||||
connectivity checks included in later versions of Chromium.
|
||||
|
||||
### How?
|
||||
|
||||
When considering a module, we recommend that you check:
|
||||
|
||||
1. the size of dependencies included
|
||||
2) the resources required to load (`require()`) it
|
||||
3. the resources required to perform the action you're interested in
|
||||
|
||||
Generating a CPU profile and a heap memory profile for loading a module can be done
|
||||
with a single command on the command line. In the example below, we're looking at
|
||||
the popular module `request`.
|
||||
|
||||
```sh
|
||||
node --cpu-prof --heap-prof -e "require('request')"
|
||||
```
|
||||
|
||||
Executing this command results in a `.cpuprofile` file and a `.heapprofile`
|
||||
file in the directory you executed it in. Both files can be analyzed using
|
||||
the Chrome Developer Tools, using the `Performance` and `Memory` tabs
|
||||
respectively.
|
||||
|
||||
![performance-cpu-prof]
|
||||
|
||||
![performance-heap-prof]
|
||||
|
||||
In this example, on the author's machine, we saw that loading `request` took
|
||||
almost half a second, whereas `node-fetch` took dramatically less memory
|
||||
and less than 50ms.
|
||||
|
||||
## 2) Loading and running code too soon
|
||||
|
||||
If you have expensive setup operations, consider deferring those. Inspect all
|
||||
the work being executed right after the application starts. Instead of firing
|
||||
off all operations right away, consider staggering them in a sequence more
|
||||
closely aligned with the user's journey.
|
||||
|
||||
In traditional Node.js development, we're used to putting all our `require()`
|
||||
statements at the top. If you're currently writing your Electron application
|
||||
using the same strategy _and_ are using sizable modules that you do not
|
||||
immediately need, apply the same strategy and defer loading to a more
|
||||
opportune time.
|
||||
|
||||
### Why?
|
||||
|
||||
Loading modules is a surprisingly expensive operation, especially on Windows.
|
||||
When your app starts, it should not make users wait for operations that are
|
||||
currently not necessary.
|
||||
|
||||
This might seem obvious, but many applications tend to do a large amount of
|
||||
work immediately after the app has launched - like checking for updates,
|
||||
downloading content used in a later flow, or performing heavy disk I/O
|
||||
operations.
|
||||
|
||||
Let's consider Visual Studio Code as an example. When you open a file, it will
|
||||
immediately display the file to you without any code highlighting, prioritizing
|
||||
your ability to interact with the text. Once it has done that work, it will
|
||||
move on to code highlighting.
|
||||
|
||||
### How?
|
||||
|
||||
Let's consider an example and assume that your application is parsing files
|
||||
in the fictitious `.foo` format. In order to do that, it relies on the
|
||||
equally fictitious `foo-parser` module. In traditional Node.js development,
|
||||
you might write code that eagerly loads dependencies:
|
||||
|
||||
```js
|
||||
const fs = require('fs')
|
||||
const fooParser = require('foo-parser')
|
||||
|
||||
class Parser {
|
||||
constructor () {
|
||||
this.files = fs.readdirSync('.')
|
||||
}
|
||||
|
||||
getParsedFiles () {
|
||||
return fooParser.parse(this.files)
|
||||
}
|
||||
}
|
||||
|
||||
const parser = new Parser()
|
||||
|
||||
module.exports = { parser }
|
||||
```
|
||||
|
||||
In the above example, we're doing a lot of work that's being executed as soon
|
||||
as the file is loaded. Do we need to get parsed files right away? Could we
|
||||
do this work a little later, when `getParsedFiles()` is actually called?
|
||||
|
||||
```js
|
||||
// "fs" is likely already being loaded, so the `require()` call is cheap
|
||||
const fs = require('fs')
|
||||
|
||||
class Parser {
|
||||
async getFiles () {
|
||||
// Touch the disk as soon as `getFiles` is called, not sooner.
|
||||
// Also, ensure that we're not blocking other operations by using
|
||||
// the asynchronous version.
|
||||
this.files = this.files || await fs.readdir('.')
|
||||
|
||||
return this.files
|
||||
}
|
||||
|
||||
async getParsedFiles () {
|
||||
// Our fictitious foo-parser is a big and expensive module to load, so
|
||||
// defer that work until we actually need to parse files.
|
||||
// Since `require()` comes with a module cache, the `require()` call
|
||||
// will only be expensive once - subsequent calls of `getParsedFiles()`
|
||||
// will be faster.
|
||||
const fooParser = require('foo-parser')
|
||||
const files = await this.getFiles()
|
||||
|
||||
return fooParser.parse(files)
|
||||
}
|
||||
}
|
||||
|
||||
// This operation is now a lot cheaper than in our previous example
|
||||
const parser = new Parser()
|
||||
|
||||
module.exports = { parser }
|
||||
```
|
||||
|
||||
In short, allocate resources "just in time" rather than allocating them all
|
||||
when your app starts.
|
||||
|
||||
## 3) Blocking the main process
|
||||
|
||||
Electron's main process (sometimes called "browser process") is special: It is
|
||||
the parent process to all your app's other processes and the primary process
|
||||
the operating system interacts with. It handles windows, interactions, and the
|
||||
communication between various components inside your app. It also houses the
|
||||
UI thread.
|
||||
|
||||
Under no circumstances should you block this process and the UI thread with
|
||||
long-running operations. Blocking the UI thread means that your entire app
|
||||
will freeze until the main process is ready to continue processing.
|
||||
|
||||
### Why?
|
||||
|
||||
The main process and its UI thread are essentially the control tower for major
|
||||
operations inside your app. When the operating system tells your app about a
|
||||
mouse click, it'll go through the main process before it reaches your window.
|
||||
If your window is rendering a buttery-smooth animation, it'll need to talk to
|
||||
the GPU process about that – once again going through the main process.
|
||||
|
||||
Electron and Chromium are careful to put heavy disk I/O and CPU-bound operations
|
||||
onto new threads to avoid blocking the UI thread. You should do the same.
|
||||
|
||||
### How?
|
||||
|
||||
Electron's powerful multi-process architecture stands ready to assist you with
|
||||
your long-running tasks, but also includes a small number of performance traps.
|
||||
|
||||
1) For long running CPU-heavy tasks, make use of
|
||||
[worker threads][worker-threads], consider moving them to the BrowserWindow, or
|
||||
(as a last resort) spawn a dedicated process.
|
||||
|
||||
2) Avoid using the synchronous IPC and the `remote` module as much as possible.
|
||||
While there are legitimate use cases, it is far too easy to unknowingly block
|
||||
the UI thread using the `remote` module.
|
||||
|
||||
3) Avoid using blocking I/O operations in the main process. In short, whenever
|
||||
core Node.js modules (like `fs` or `child_process`) offer a synchronous or an
|
||||
asynchronous version, you should prefer the asynchronous and non-blocking
|
||||
variant.
|
||||
|
||||
|
||||
## 4) Blocking the renderer process
|
||||
|
||||
Since Electron ships with a current version of Chrome, you can make use of the
|
||||
latest and greatest features the Web Platform offers to defer or offload heavy
|
||||
operations in a way that keeps your app smooth and responsive.
|
||||
|
||||
### Why?
|
||||
|
||||
Your app probably has a lot of JavaScript to run in the renderer process. The
|
||||
trick is to execute operations as quickly as possible without taking away
|
||||
resources needed to keep scrolling smooth, respond to user input, or animations
|
||||
at 60fps.
|
||||
|
||||
Orchestrating the flow of operations in your renderer's code is
|
||||
particularly useful if users complain about your app sometimes "stuttering".
|
||||
|
||||
### How?
|
||||
|
||||
Generally speaking, all advice for building performant web apps for modern
|
||||
browsers apply to Electron's renderers, too. The two primary tools at your
|
||||
disposal are currently `requestIdleCallback()` for small operations and
|
||||
`Web Workers` for long-running operations.
|
||||
|
||||
*`requestIdleCallback()`* allows developers to queue up a function to be
|
||||
executed as soon as the process is entering an idle period. It enables you to
|
||||
perform low-priority or background work without impacting the user experience.
|
||||
For more information about how to use it,
|
||||
[check out its documentation on MDN][request-idle-callback].
|
||||
|
||||
*Web Workers* are a powerful tool to run code on a separate thread. There are
|
||||
some caveats to consider – consult Electron's
|
||||
[multithreading documentation][multithreading] and the
|
||||
[MDN documentation for Web Workers][web-workers]. They're an ideal solution
|
||||
for any operation that requires a lot of CPU power for an extended period of
|
||||
time.
|
||||
|
||||
|
||||
## 5) Unnecessary polyfills
|
||||
|
||||
One of Electron's great benefits is that you know exactly which engine will
|
||||
parse your JavaScript, HTML, and CSS. If you're re-purposing code that was
|
||||
written for the web at large, make sure to not polyfill features included in
|
||||
Electron.
|
||||
|
||||
### Why?
|
||||
|
||||
When building a web application for today's Internet, the oldest environments
|
||||
dictate what features you can and cannot use. Even though Electron supports
|
||||
well-performing CSS filters and animations, an older browser might not. Where
|
||||
you could use WebGL, your developers may have chosen a more resource-hungry
|
||||
solution to support older phones.
|
||||
|
||||
When it comes to JavaScript, you may have included toolkit libraries like
|
||||
jQuery for DOM selectors or polyfills like the `regenerator-runtime` to support
|
||||
`async/await`.
|
||||
|
||||
It is rare for a JavaScript-based polyfill to be faster than the equivalent
|
||||
native feature in Electron. Do not slow down your Electron app by shipping your
|
||||
own version of standard web platform features.
|
||||
|
||||
### How?
|
||||
|
||||
Operate under the assumption that polyfills in current versions of Electron
|
||||
are unnecessary. If you have doubts, check [caniuse.com][https://caniuse.com/]
|
||||
and check if the [version of Chromium used in your Electron version](../api/process.md#processversionschrome-readonly)
|
||||
supports the feature you desire.
|
||||
|
||||
In addition, carefully examine the libraries you use. Are they really necessary?
|
||||
`jQuery`, for example, was such a success that many of its features are now part
|
||||
of the [standard JavaScript feature set available][jquery-need].
|
||||
|
||||
If you're using a transpiler/compiler like TypeScript, examine its configuration
|
||||
and ensure that you're targeting the latest ECMAScript version supported by
|
||||
Electron.
|
||||
|
||||
|
||||
## 6) Unnecessary or blocking network requests
|
||||
|
||||
Avoid fetching rarely changing resources from the internet if they could easily
|
||||
be bundled with your application.
|
||||
|
||||
### Why?
|
||||
|
||||
Many users of Electron start with an entirely web-based app that they're
|
||||
turning into a desktop application. As web developers, we are used to loading
|
||||
resources from a variety of content delivery networks. Now that you are
|
||||
shipping a proper desktop application, attempt to "cut the cord" where possible
|
||||
- and avoid letting your users wait for resources that never change and could
|
||||
easily be included in your app.
|
||||
|
||||
A typical example is Google Fonts. Many developers make use of Google's
|
||||
impressive collection of free fonts, which comes with a content delivery
|
||||
network. The pitch is straightforward: Include a few lines of CSS and Google
|
||||
will take care of the rest.
|
||||
|
||||
When building an Electron app, your users are better served if you download
|
||||
the fonts and include them in your app's bundle.
|
||||
|
||||
### How?
|
||||
|
||||
In an ideal world, your application wouldn't need the network to operate at
|
||||
all. To get there, you must understand what resources your app is downloading
|
||||
\- and how large those resources are.
|
||||
|
||||
To do so, open up the developer tools. Navigate to the `Network` tab and check
|
||||
the `Disable cache` option. Then, reload your renderer. Unless your app
|
||||
prohibits such reloads, you can usually trigger a reload by hitting `Cmd + R`
|
||||
or `Ctrl + R` with the developer tools in focus.
|
||||
|
||||
The tools will now meticulously record all network requests. In a first pass,
|
||||
take stock of all the resources being downloaded, focusing on the larger files
|
||||
first. Are any of them images, fonts, or media files that don't change and
|
||||
could be included with your bundle? If so, include them.
|
||||
|
||||
As a next step, enable `Network Throttling`. Find the drop-down that currently
|
||||
reads `Online` and select a slower speed such as `Fast 3G`. Reload your
|
||||
renderer and see if there are any resources that your app is unnecessarily
|
||||
waiting for. In many cases, an app will wait for a network request to complete
|
||||
despite not actually needing the involved resource.
|
||||
|
||||
As a tip, loading resources from the Internet that you might want to change
|
||||
without shipping an application update is a powerful strategy. For advanced
|
||||
control over how resources are being loaded, consider investing in
|
||||
[Service Workers][service-workers].
|
||||
|
||||
## 7) Bundle your code
|
||||
|
||||
As already pointed out in
|
||||
"[Loading and running code too soon](#2-loading-and-running-code-too-soon)",
|
||||
calling `require()` is an expensive operation. If you are able to do so,
|
||||
bundle your application's code into a single file.
|
||||
|
||||
### Why?
|
||||
|
||||
Modern JavaScript development usually involves many files and modules. While
|
||||
that's perfectly fine for developing with Electron, we heavily recommend that
|
||||
you bundle all your code into one single file to ensure that the overhead
|
||||
included in calling `require()` is only paid once when your application loads.
|
||||
|
||||
### How?
|
||||
|
||||
There are numerous JavaScript bundlers out there and we know better than to
|
||||
anger the community by recommending one tool over another. We do however
|
||||
recommend that you use a bundler that is able to handle Electron's unique
|
||||
environment that needs to handle both Node.js and browser environments.
|
||||
|
||||
As of writing this article, the popular choices include [Webpack][webpack],
|
||||
[Parcel][parcel], and [rollup.js][rollup].
|
||||
|
||||
[security]: ./security.md
|
||||
[performance-cpu-prof]: ../images/performance-cpu-prof.png
|
||||
[performance-heap-prof]: ../images/performance-heap-prof.png
|
||||
[chrome-devtools-tutorial]: https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/
|
||||
[worker-threads]: https://nodejs.org/api/worker_threads.html
|
||||
[web-workers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
|
||||
[request-idle-callback]: https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback
|
||||
[multithreading]: ./multithreading.md
|
||||
[caniuse]: https://caniuse.com/
|
||||
[jquery-need]: http://youmightnotneedjquery.com/
|
||||
[service-workers]: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
|
||||
[webpack]: https://webpack.js.org/
|
||||
[parcel]: https://parceljs.org/
|
||||
[rollup]: https://rollupjs.org/
|
||||
[vscode-first-second]: https://www.youtube.com/watch?v=r0OeHRUCCb4
|
||||
@@ -43,7 +43,8 @@ When releasing your product, you’re also shipping a bundle composed of Electro
|
||||
Chromium shared library and Node.js. Vulnerabilities affecting these components
|
||||
may impact the security of your application. By updating Electron to the latest
|
||||
version, you ensure that critical vulnerabilities (such as *nodeIntegration bypasses*)
|
||||
are already patched and cannot be exploited in your application.
|
||||
are already patched and cannot be exploited in your application. For more information,
|
||||
see "[Use a current version of Electron](#17-use-a-current-version-of-electron)".
|
||||
|
||||
* **Evaluate your dependencies.** While NPM provides half a million reusable packages,
|
||||
it is your responsibility to choose trusted 3rd-party libraries. If you use outdated
|
||||
@@ -101,6 +102,7 @@ You should at least follow these steps to improve the security of your applicati
|
||||
14. [Do not use `openExternal` with untrusted content](#14-do-not-use-openexternal-with-untrusted-content)
|
||||
15. [Disable the `remote` module](#15-disable-the-remote-module)
|
||||
16. [Filter the `remote` module](#16-filter-the-remote-module)
|
||||
17. [Use a current version of Electron](#17-use-a-current-version-of-electron)
|
||||
|
||||
To automate the detection of misconfigurations and insecure patterns, it is
|
||||
possible to use
|
||||
@@ -161,7 +163,7 @@ for an attacker to harm your users should they gain the ability to execute
|
||||
JavaScript on your website.
|
||||
|
||||
After this, you can grant additional permissions for specific hosts. For example,
|
||||
if you are opening a BrowserWindow pointed at `https://example.com/", you can
|
||||
if you are opening a BrowserWindow pointed at `https://example.com/`, you can
|
||||
give that website exactly the abilities it needs, but no more.
|
||||
|
||||
### Why?
|
||||
@@ -511,7 +513,7 @@ no circumstances should you enable features speculatively.
|
||||
// Bad
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
enableBlinkFeatures: ['ExecCommandInJavaScript']
|
||||
enableBlinkFeatures: 'ExecCommandInJavaScript'
|
||||
}
|
||||
})
|
||||
```
|
||||
@@ -830,6 +832,29 @@ app.on('remote-get-guest-web-contents', (event, webContents, guestWebContents) =
|
||||
})
|
||||
```
|
||||
|
||||
## 17) Use a current version of Electron
|
||||
|
||||
You should strive for always using the latest available version of Electron.
|
||||
Whenever a new major version is released, you should attempt to update your
|
||||
app as quickly as possible.
|
||||
|
||||
### Why?
|
||||
|
||||
An application built with an older version of Electron, Chromium, and Node.js
|
||||
is an easier target than an application that is using more recent versions of
|
||||
those components. Generally speaking, security issues and exploits for older
|
||||
versions of Chromium and Node.js are more widely available.
|
||||
|
||||
Both Chromium and Node.js are impressive feats of engineering built by
|
||||
thousands of talented developers. Given their popularity, their security is
|
||||
carefully tested and analyzed by equally skilled security researchers. Many of
|
||||
those researchers [disclose vulnerabilities responsibly][responsible-disclosure],
|
||||
which generally means that researchers will give Chromium and Node.js some time
|
||||
to fix issues before publishing them. Your application will be more secure if
|
||||
it is running a recent version of Electron (and thus, Chromium and Node.js) for
|
||||
which potential security issues are not as widely known.
|
||||
|
||||
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[browser-view]: ../api/browser-view.md
|
||||
[webview-tag]: ../api/webview-tag.md
|
||||
@@ -838,3 +863,4 @@ app.on('remote-get-guest-web-contents', (event, webContents, guestWebContents) =
|
||||
[will-navigate]: ../api/web-contents.md#event-will-navigate
|
||||
[open-external]: ../api/shell.md#shellopenexternalurl-options-callback
|
||||
[sandbox]: ../api/sandbox-option.md
|
||||
[responsible-disclosure]: https://en.wikipedia.org/wiki/Responsible_disclosure
|
||||
|
||||
@@ -86,8 +86,8 @@ Windows 7 and later are supported, older operating systems are not supported
|
||||
(and do not work).
|
||||
|
||||
Both `ia32` (`x86`) and `x64` (`amd64`) binaries are provided for Windows.
|
||||
Running Electron apps on Windows for ARM devices is possible by using the
|
||||
ia32 binary.
|
||||
[Electron 6.0.8 and later add native support for Windows on Arm (`arm64`) devices](windows-arm.md).
|
||||
Running apps packaged with previous versions is possible using the ia32 binary.
|
||||
|
||||
### Linux
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ const options = {
|
||||
port: 9515, // "9515" is the port opened by chrome driver.
|
||||
desiredCapabilities: {
|
||||
browserName: 'chrome',
|
||||
chromeOptions: {
|
||||
'goog:chromeOptions': {
|
||||
binary: '/Path-to-Your-App/electron', // Path to your Electron binary.
|
||||
args: [/* cli arguments */] // Optional, perhaps 'app=' + /path/to/your/app/
|
||||
}
|
||||
|
||||
95
docs/tutorial/windows-arm.md
Normal file
95
docs/tutorial/windows-arm.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Windows 10 on Arm
|
||||
|
||||
If your app runs with Electron 6.0.8 or later, you can now build it for Windows 10 on Arm. This considerably improves performance, but requires recompilation of any native modules used in your app. It may also require small fixups to your build and packaging scripts.
|
||||
|
||||
## Running a basic app
|
||||
If your app doesn't use any native modules, then it's really easy to create an Arm version of your app.
|
||||
|
||||
1. Make sure that your app's `node_modules` directory is empty.
|
||||
2. Using a _Command Prompt_, run `set npm_config_arch=arm64` before running `npm install`/`yarn install` as usual.
|
||||
3. [If you have electron installed as a development dependency](first-app.md), npm will download and unpack the arm64 version. You can then package and distribute your app as normal.
|
||||
|
||||
## General considerations
|
||||
|
||||
### Architecture-specific code
|
||||
|
||||
Lots of Windows-specific code contains if... else logic that selects between either the x64 or x86 architectures.
|
||||
|
||||
```js
|
||||
if (process.arch === 'x64') {
|
||||
// Do 64-bit thing...
|
||||
} else {
|
||||
// Do 32-bit thing...
|
||||
}
|
||||
```
|
||||
|
||||
If you want to target arm64, logic like this will typically select the wrong architecture, so carefully check your application and build scripts for conditions like this. In custom build and packaging scripts, you should always check the value of `npm_config_arch` in the environment, rather than relying on the current process arch.
|
||||
|
||||
### Native modules
|
||||
If you use native modules, you must make sure that that they compile against v142 of the MSVC compiler (provided in Visual Studio 2017). You must also check that any pre-built `.dll` or or `.lib` files provided or referenced by the native module are available for Windows on Arm.
|
||||
|
||||
### Testing your app
|
||||
To test your app, use a Windows on Arm device running Windows 10 (version 1903 or later). Make sure that you copy your application over to the target device - Chromium's sandbox will not work correctly when loading your application assets from a network location.
|
||||
|
||||
## Development prerequisites
|
||||
### Node.js/node-gyp
|
||||
|
||||
[Node.js v12.9.0 or later is recommended.](https://nodejs.org/en/) If updating to a new version of Node is undesirable, you can instead [update npm's copy of node-gyp manually](https://github.com/nodejs/node-gyp/wiki/Updating-npm's-bundled-node-gyp) to version 5.0.2 or later, which contains the required changes to compile native modules for Arm.
|
||||
|
||||
### Visual Studio 2017
|
||||
Visual Studio 2017 (any edition) is required for cross-compiling native modules. You can download Visual Studio Community 2017 via Microsoft's [Visual Studio Dev Essentials program](https://visualstudio.microsoft.com/dev-essentials/). After installation, you can add the Arm-specific components by running the following from a _Command Prompt_:
|
||||
|
||||
```powershell
|
||||
vs_installer.exe ^
|
||||
--add Microsoft.VisualStudio.Workload.NativeDesktop ^
|
||||
--add Microsoft.VisualStudio.Component.VC.ATLMFC ^
|
||||
--add Microsoft.VisualStudio.Component.VC.Tools.ARM64 ^
|
||||
--add Microsoft.VisualStudio.Component.VC.MFC.ARM64 ^
|
||||
--includeRecommended
|
||||
```
|
||||
|
||||
#### Creating a cross-compilation command prompt
|
||||
Setting `npm_config_arch=arm64` in the environment creates the correct arm64 `.obj` files, but the standard _Developer Command Prompt for VS 2017_ will use the x64 linker. To fix this:
|
||||
|
||||
1. Duplicate the _x64_x86 Cross Tools Command Prompt for VS 2017_ shortcut (e.g. by locating it in the start menu, right clicking, selecting _Open File Location_, copying and pasting) to somewhere convenient.
|
||||
2. Right click the new shortcut and choose _Properties_.
|
||||
3. Change the _Target_ field to read `vcvarsamd64_arm64.bat` at the end instead of `vcvarsamd64_x86.bat`.
|
||||
|
||||
If done successfully, the command prompt should print something similar to this on startup:
|
||||
|
||||
```bat
|
||||
**********************************************************************
|
||||
** Visual Studio 2017 Developer Command Prompt v15.9.15
|
||||
** Copyright (c) 2017 Microsoft Corporation
|
||||
**********************************************************************
|
||||
[vcvarsall.bat] Environment initialized for: 'x64_arm64'
|
||||
```
|
||||
|
||||
If you want to develop your application directly on a Windows on Arm device, substitute `vcvarsx86_arm64.bat` in _Target_ so that cross-compilation can happen with the device's x86 emulation.
|
||||
|
||||
### Linking against the correct `node.lib`
|
||||
|
||||
By default, `node-gyp` unpacks Electron's node headers and downloads the x86 and x64 versions of `node.lib` into `%APPDATA%\..\Local\node-gyp\Cache`, but it does not download the arm64 version ([a fix for this is in development](https://github.com/nodejs/node-gyp/pull/1875).) To fix this:
|
||||
|
||||
1. Download the arm64 `node.lib` from https://atom.io/download/v6.0.9/win-arm64/node.lib
|
||||
2. Move it to `%APPDATA%\..\Local\node-gyp\Cache\6.0.9\arm64\node.lib`
|
||||
|
||||
Substitute `6.0.9` for the version you're using.
|
||||
|
||||
|
||||
## Cross-compiling native modules
|
||||
After completing all of the above, open your cross-compilation command prompt and run `set npm_config_arch=arm64`. Then use `npm install` to build your project as normal. As with cross-compiling x86 modules, you may need to remove `node_modules` to force recompilation of native modules if they were previously compiled for another architecture.
|
||||
|
||||
## Debugging native modules
|
||||
|
||||
Debugging native modules can be done with Visual Studio 2017 (running on your development machine) and corresponding [Visual Studio Remote Debugger](https://docs.microsoft.com/en-us/visualstudio/debugger/remote-debugging-cpp?view=vs-2019) running on the target device. To debug:
|
||||
|
||||
1. Lanch your app `.exe` on the target device via the _Command Prompt_ (passing `--inspect-brk` to pause it before any native modules are loaded).
|
||||
2. Launch Visual Studio 2017 on your development machine.
|
||||
3. Connect to the target device by selecting _Debug > Attach to Process..._ and enter the device's IP address and the port number displayed by the Visual Studio Remote Debugger tool.
|
||||
4. Click _Refresh_ and select the [appropriate Electron process to attach](../development/debug-instructions-windows.md).
|
||||
5. You may need to make sure that any symbols for native modules in your app are loaded correctly. To configure this, head to _Debug > Options..._ in Visual Studio 2017, and add the folders containing your `.pdb` symbols under _Debugging > Symbols_.
|
||||
5. Once attached, set any appropriate breakpoints and resume JavaScript execution using Chrome's [remote tools for Node](debugging-main-process.md).
|
||||
|
||||
## Getting additional help
|
||||
If you encounter a problem with this documentation, or if your app works when compiled for x86 but not for arm64, please [file an issue](../development/issues.md) with "Windows on Arm" in the title.
|
||||
@@ -147,7 +147,7 @@ template("electron_paks") {
|
||||
source_patterns = [
|
||||
"${root_gen_dir}/chrome/platform_locale_settings_",
|
||||
"${root_gen_dir}/components/strings/components_strings_",
|
||||
"${root_gen_dir}/content/app/strings/content_strings_",
|
||||
"${root_gen_dir}/third_party/blink/public/strings/blink_strings_",
|
||||
"${root_gen_dir}/device/bluetooth/strings/bluetooth_strings_",
|
||||
"${root_gen_dir}/services/strings/services_strings_",
|
||||
"${root_gen_dir}/ui/strings/app_locale_settings_",
|
||||
@@ -156,9 +156,9 @@ template("electron_paks") {
|
||||
deps = [
|
||||
"//chrome/app/resources:platform_locale_settings",
|
||||
"//components/strings:components_strings",
|
||||
"//content/app/strings",
|
||||
"//device/bluetooth/strings",
|
||||
"//services/strings",
|
||||
"//third_party/blink/public/strings",
|
||||
"//ui/strings:app_locale_settings",
|
||||
"//ui/strings:ui_strings",
|
||||
]
|
||||
|
||||
@@ -9,12 +9,11 @@ auto_filenames = {
|
||||
"docs/api/browser-view.md",
|
||||
"docs/api/browser-window-proxy.md",
|
||||
"docs/api/browser-window.md",
|
||||
"docs/api/chrome-command-line-switches.md",
|
||||
"docs/api/client-request.md",
|
||||
"docs/api/clipboard.md",
|
||||
"docs/api/command-line-switches.md",
|
||||
"docs/api/command-line.md",
|
||||
"docs/api/content-tracing.md",
|
||||
"docs/api/context-bridge.md",
|
||||
"docs/api/cookies.md",
|
||||
"docs/api/crash-reporter.md",
|
||||
"docs/api/debugger.md",
|
||||
@@ -111,6 +110,7 @@ auto_filenames = {
|
||||
"docs/api/structures/remove-password.md",
|
||||
"docs/api/structures/scrubber-item.md",
|
||||
"docs/api/structures/segmented-control-segment.md",
|
||||
"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",
|
||||
@@ -131,24 +131,22 @@ auto_filenames = {
|
||||
"lib/browser/api/module-keys.js",
|
||||
"lib/common/api/clipboard.js",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.js",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/buffer-utils.ts",
|
||||
"lib/common/clipboard-utils.ts",
|
||||
"lib/common/crash-reporter.js",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/common/error-utils.ts",
|
||||
"lib/common/is-promise.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/remote/buffer-utils.ts",
|
||||
"lib/common/remote/is-promise.ts",
|
||||
"lib/common/web-view-methods.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
"lib/renderer/api/crash-reporter.js",
|
||||
"lib/renderer/api/desktop-capturer.ts",
|
||||
"lib/renderer/api/ipc-renderer.js",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/remote.js",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/callbacks-registry.ts",
|
||||
"lib/renderer/chrome-api.ts",
|
||||
"lib/renderer/content-scripts-injector.ts",
|
||||
"lib/renderer/extensions/event.ts",
|
||||
@@ -158,6 +156,7 @@ auto_filenames = {
|
||||
"lib/renderer/inspector.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/renderer/remote/callbacks-registry.ts",
|
||||
"lib/renderer/security-warnings.ts",
|
||||
"lib/renderer/web-frame-init.ts",
|
||||
"lib/renderer/web-view/guest-view-internal.ts",
|
||||
@@ -166,9 +165,8 @@ auto_filenames = {
|
||||
"lib/renderer/web-view/web-view-element.ts",
|
||||
"lib/renderer/web-view/web-view-impl.ts",
|
||||
"lib/renderer/web-view/web-view-init.ts",
|
||||
"lib/renderer/window-setup.ts",
|
||||
"lib/sandboxed_renderer/api/exports/electron.js",
|
||||
"lib/sandboxed_renderer/api/module-list.js",
|
||||
"lib/sandboxed_renderer/api/exports/electron.ts",
|
||||
"lib/sandboxed_renderer/api/module-list.ts",
|
||||
"lib/sandboxed_renderer/init.js",
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
@@ -178,7 +176,6 @@ auto_filenames = {
|
||||
isolated_bundle_deps = [
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/common/error-utils.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/isolated_renderer/init.js",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
@@ -193,7 +190,6 @@ auto_filenames = {
|
||||
content_script_bundle_deps = [
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/common/error-utils.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/content_script/init.js",
|
||||
"lib/renderer/chrome-api.ts",
|
||||
"lib/renderer/extensions/event.ts",
|
||||
@@ -219,7 +215,7 @@ auto_filenames = {
|
||||
"lib/browser/api/content-tracing.js",
|
||||
"lib/browser/api/crash-reporter.js",
|
||||
"lib/browser/api/dialog.js",
|
||||
"lib/browser/api/exports/electron.js",
|
||||
"lib/browser/api/exports/electron.ts",
|
||||
"lib/browser/api/global-shortcut.js",
|
||||
"lib/browser/api/in-app-purchase.js",
|
||||
"lib/browser/api/ipc-main.ts",
|
||||
@@ -227,7 +223,7 @@ auto_filenames = {
|
||||
"lib/browser/api/menu-item.js",
|
||||
"lib/browser/api/menu-utils.js",
|
||||
"lib/browser/api/menu.js",
|
||||
"lib/browser/api/module-list.js",
|
||||
"lib/browser/api/module-list.ts",
|
||||
"lib/browser/api/native-theme.ts",
|
||||
"lib/browser/api/net-log.js",
|
||||
"lib/browser/api/net.js",
|
||||
@@ -259,29 +255,30 @@ auto_filenames = {
|
||||
"lib/browser/guest-view-manager.js",
|
||||
"lib/browser/guest-window-manager.js",
|
||||
"lib/browser/init.ts",
|
||||
"lib/browser/ipc-main-impl.ts",
|
||||
"lib/browser/ipc-main-internal-utils.ts",
|
||||
"lib/browser/ipc-main-internal.ts",
|
||||
"lib/browser/navigation-controller.js",
|
||||
"lib/browser/objects-registry.js",
|
||||
"lib/browser/remote/objects-registry.ts",
|
||||
"lib/browser/remote/server.ts",
|
||||
"lib/browser/rpc-server.js",
|
||||
"lib/browser/utils.ts",
|
||||
"lib/common/api/clipboard.js",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/exports/electron.js",
|
||||
"lib/common/api/module-list.js",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/buffer-utils.ts",
|
||||
"lib/common/clipboard-utils.ts",
|
||||
"lib/common/crash-reporter.js",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/common/error-utils.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/is-promise.ts",
|
||||
"lib/common/parse-features-string.js",
|
||||
"lib/common/remote/buffer-utils.ts",
|
||||
"lib/common/remote/is-promise.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/web-view-methods.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"package.json",
|
||||
@@ -293,29 +290,26 @@ auto_filenames = {
|
||||
"lib/browser/api/module-keys.js",
|
||||
"lib/common/api/clipboard.js",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/exports/electron.js",
|
||||
"lib/common/api/module-list.js",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/buffer-utils.ts",
|
||||
"lib/common/clipboard-utils.ts",
|
||||
"lib/common/crash-reporter.js",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/common/error-utils.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/is-promise.ts",
|
||||
"lib/common/remote/buffer-utils.ts",
|
||||
"lib/common/remote/is-promise.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/web-view-methods.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
"lib/renderer/api/crash-reporter.js",
|
||||
"lib/renderer/api/desktop-capturer.ts",
|
||||
"lib/renderer/api/exports/electron.js",
|
||||
"lib/renderer/api/ipc-renderer.js",
|
||||
"lib/renderer/api/module-list.js",
|
||||
"lib/renderer/api/exports/electron.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/remote.js",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/callbacks-registry.ts",
|
||||
"lib/renderer/chrome-api.ts",
|
||||
"lib/renderer/content-scripts-injector.ts",
|
||||
"lib/renderer/extensions/event.ts",
|
||||
@@ -326,6 +320,7 @@ auto_filenames = {
|
||||
"lib/renderer/inspector.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/renderer/remote/callbacks-registry.ts",
|
||||
"lib/renderer/security-warnings.ts",
|
||||
"lib/renderer/web-frame-init.ts",
|
||||
"lib/renderer/web-view/guest-view-internal.ts",
|
||||
@@ -345,30 +340,28 @@ auto_filenames = {
|
||||
"lib/browser/api/module-keys.js",
|
||||
"lib/common/api/clipboard.js",
|
||||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/exports/electron.js",
|
||||
"lib/common/api/module-list.js",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/buffer-utils.ts",
|
||||
"lib/common/clipboard-utils.ts",
|
||||
"lib/common/crash-reporter.js",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/electron-binding-setup.ts",
|
||||
"lib/common/error-utils.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/is-promise.ts",
|
||||
"lib/common/remote/buffer-utils.ts",
|
||||
"lib/common/remote/is-promise.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/type-utils.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
"lib/renderer/api/crash-reporter.js",
|
||||
"lib/renderer/api/desktop-capturer.ts",
|
||||
"lib/renderer/api/exports/electron.js",
|
||||
"lib/renderer/api/ipc-renderer.js",
|
||||
"lib/renderer/api/module-list.js",
|
||||
"lib/renderer/api/exports/electron.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/remote.js",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/callbacks-registry.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/renderer/remote/callbacks-registry.ts",
|
||||
"lib/renderer/webpack-provider.ts",
|
||||
"lib/worker/init.js",
|
||||
"package.json",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
filenames = {
|
||||
default_app_ts_sources = [
|
||||
"default_app/default_app.ts",
|
||||
"default_app/index.ts",
|
||||
"default_app/main.ts",
|
||||
"default_app/preload.ts",
|
||||
]
|
||||
@@ -93,8 +94,8 @@ filenames = {
|
||||
"shell/browser/api/atom_api_top_level_window.h",
|
||||
"shell/browser/api/atom_api_tray.cc",
|
||||
"shell/browser/api/atom_api_tray.h",
|
||||
"shell/browser/api/atom_api_url_loader.cc",
|
||||
"shell/browser/api/atom_api_url_loader.h",
|
||||
"shell/browser/api/atom_api_url_request_ns.cc",
|
||||
"shell/browser/api/atom_api_url_request_ns.h",
|
||||
"shell/browser/api/atom_api_view.cc",
|
||||
"shell/browser/api/atom_api_view.h",
|
||||
"shell/browser/api/atom_api_web_contents.cc",
|
||||
@@ -129,6 +130,10 @@ filenames = {
|
||||
"shell/browser/auto_updater.cc",
|
||||
"shell/browser/auto_updater.h",
|
||||
"shell/browser/auto_updater_mac.mm",
|
||||
"shell/browser/atom_autofill_driver_factory.cc",
|
||||
"shell/browser/atom_autofill_driver_factory.h",
|
||||
"shell/browser/atom_autofill_driver.cc",
|
||||
"shell/browser/atom_autofill_driver.h",
|
||||
"shell/browser/atom_browser_client.cc",
|
||||
"shell/browser/atom_browser_client.h",
|
||||
"shell/browser/atom_browser_context.cc",
|
||||
@@ -353,7 +358,6 @@ filenames = {
|
||||
"shell/browser/ui/tray_icon_observer.h",
|
||||
"shell/browser/ui/tray_icon_win.cc",
|
||||
"shell/browser/ui/views/atom_views_delegate.cc",
|
||||
"shell/browser/ui/views/atom_views_delegate_win.cc",
|
||||
"shell/browser/ui/views/atom_views_delegate.h",
|
||||
"shell/browser/ui/views/autofill_popup_view.cc",
|
||||
"shell/browser/ui/views/autofill_popup_view.h",
|
||||
@@ -431,17 +435,11 @@ filenames = {
|
||||
"shell/common/api/electron_bindings.cc",
|
||||
"shell/common/api/electron_bindings.h",
|
||||
"shell/common/api/constructor.h",
|
||||
"shell/common/api/event_emitter_caller.cc",
|
||||
"shell/common/api/event_emitter_caller.h",
|
||||
"shell/common/api/event_emitter_caller_deprecated.cc",
|
||||
"shell/common/api/event_emitter_caller_deprecated.h",
|
||||
"shell/common/api/features.cc",
|
||||
"shell/common/api/locker.cc",
|
||||
"shell/common/api/locker.h",
|
||||
"shell/common/api/object_life_monitor.cc",
|
||||
"shell/common/api/object_life_monitor.h",
|
||||
"shell/common/api/remote_callback_freer.cc",
|
||||
"shell/common/api/remote_callback_freer.h",
|
||||
"shell/common/api/remote_object_freer.cc",
|
||||
"shell/common/api/remote_object_freer.h",
|
||||
"shell/common/asar/archive.cc",
|
||||
"shell/common/asar/archive.h",
|
||||
"shell/common/asar/asar_util.cc",
|
||||
@@ -471,12 +469,34 @@ filenames = {
|
||||
"shell/common/crash_reporter/linux/crash_dump_handler.h",
|
||||
"shell/common/crash_reporter/win/crash_service_main.cc",
|
||||
"shell/common/crash_reporter/win/crash_service_main.h",
|
||||
"shell/common/gin_converters/callback_converter_gin_adapter.h",
|
||||
"shell/common/gin_converters/gurl_converter_gin_adapter.h",
|
||||
"shell/common/gin_converters/net_converter_gin_adapter.h",
|
||||
"shell/common/gin_converters/callback_converter.h",
|
||||
"shell/common/gin_converters/file_dialog_converter.cc",
|
||||
"shell/common/gin_converters/file_dialog_converter.h",
|
||||
"shell/common/gin_converters/file_path_converter.h",
|
||||
"shell/common/gin_converters/gurl_converter.h",
|
||||
"shell/common/gin_converters/image_converter.cc",
|
||||
"shell/common/gin_converters/image_converter.h",
|
||||
"shell/common/gin_converters/native_mate_handle_converter.h",
|
||||
"shell/common/gin_converters/message_box_converter.cc",
|
||||
"shell/common/gin_converters/message_box_converter.h",
|
||||
"shell/common/gin_converters/native_window_converter.h",
|
||||
"shell/common/gin_converters/net_converter.cc",
|
||||
"shell/common/gin_converters/net_converter.h",
|
||||
"shell/common/gin_converters/std_converter.h",
|
||||
"shell/common/gin_converters/value_converter_gin_adapter.h",
|
||||
"shell/common/gin_util.h",
|
||||
"shell/common/gin_helper/callback.cc",
|
||||
"shell/common/gin_helper/callback.h",
|
||||
"shell/common/gin_helper/destroyable.cc",
|
||||
"shell/common/gin_helper/destroyable.h",
|
||||
"shell/common/gin_helper/dictionary.h",
|
||||
"shell/common/gin_helper/error_thrower.cc",
|
||||
"shell/common/gin_helper/error_thrower.h",
|
||||
"shell/common/gin_helper/event_emitter_caller.cc",
|
||||
"shell/common/gin_helper/event_emitter_caller.h",
|
||||
"shell/common/gin_helper/function_template.cc",
|
||||
"shell/common/gin_helper/function_template.h",
|
||||
"shell/common/gin_helper/object_template_builder.cc",
|
||||
"shell/common/gin_helper/object_template_builder.h",
|
||||
"shell/common/heap_snapshot.cc",
|
||||
"shell/common/heap_snapshot.h",
|
||||
"shell/common/key_weak_map.h",
|
||||
@@ -492,22 +512,18 @@ filenames = {
|
||||
"shell/common/native_mate_converters/accelerator_converter.h",
|
||||
"shell/common/native_mate_converters/blink_converter.cc",
|
||||
"shell/common/native_mate_converters/blink_converter.h",
|
||||
"shell/common/native_mate_converters/callback.cc",
|
||||
"shell/common/native_mate_converters/callback.h",
|
||||
"shell/common/native_mate_converters/callback_converter_deprecated.cc",
|
||||
"shell/common/native_mate_converters/callback_converter_deprecated.h",
|
||||
"shell/common/native_mate_converters/content_converter.cc",
|
||||
"shell/common/native_mate_converters/content_converter.h",
|
||||
"shell/common/native_mate_converters/file_dialog_converter.cc",
|
||||
"shell/common/native_mate_converters/file_dialog_converter.h",
|
||||
"shell/common/native_mate_converters/message_box_converter.cc",
|
||||
"shell/common/native_mate_converters/message_box_converter.h",
|
||||
"shell/common/native_mate_converters/file_path_converter.h",
|
||||
"shell/common/native_mate_converters/gfx_converter.cc",
|
||||
"shell/common/native_mate_converters/gfx_converter.h",
|
||||
"shell/common/native_mate_converters/gurl_converter.h",
|
||||
"shell/common/native_mate_converters/image_converter.cc",
|
||||
"shell/common/native_mate_converters/image_converter.h",
|
||||
"shell/common/native_mate_converters/map_converter.h",
|
||||
"shell/common/native_mate_converters/net_converter.cc",
|
||||
"shell/common/native_mate_converters/native_window_converter.h",
|
||||
"shell/common/native_mate_converters/net_converter.h",
|
||||
"shell/common/native_mate_converters/network_converter.cc",
|
||||
"shell/common/native_mate_converters/network_converter.h",
|
||||
@@ -537,10 +553,6 @@ filenames = {
|
||||
"shell/common/promise_util.cc",
|
||||
"shell/common/skia_util.h",
|
||||
"shell/common/skia_util.cc",
|
||||
"shell/renderer/api/context_bridge/render_frame_context_bridge_store.cc",
|
||||
"shell/renderer/api/context_bridge/render_frame_context_bridge_store.h",
|
||||
"shell/renderer/api/atom_api_context_bridge.cc",
|
||||
"shell/renderer/api/atom_api_context_bridge.h",
|
||||
"shell/renderer/api/atom_api_renderer_ipc.cc",
|
||||
"shell/renderer/api/atom_api_spell_check_client.cc",
|
||||
"shell/renderer/api/atom_api_spell_check_client.h",
|
||||
|
||||
@@ -105,9 +105,9 @@ if (process.platform === 'linux') {
|
||||
}
|
||||
|
||||
// Routes the events to webContents.
|
||||
const events = ['certificate-error', 'select-client-certificate']
|
||||
const events = ['login', 'certificate-error', 'select-client-certificate']
|
||||
for (const name of events) {
|
||||
app.on(name as 'certificate-error', (event, webContents, ...args: any[]) => {
|
||||
app.on(name as 'login', (event, webContents, ...args: any[]) => {
|
||||
webContents.emit(name, event, ...args)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ BrowserWindow.prototype._init = function () {
|
||||
|
||||
// Hide the auto-hide menu when webContents is focused.
|
||||
this.webContents.on('activate', () => {
|
||||
if (process.platform !== 'darwin' && this.autoHideMenuBar && this.isMenuBarVisible()) {
|
||||
if (process.platform !== 'darwin' && this.isMenuBarAutoHide() && this.isMenuBarVisible()) {
|
||||
this.setMenuBarVisibility(false)
|
||||
}
|
||||
})
|
||||
@@ -116,8 +116,10 @@ BrowserWindow.getFocusedWindow = () => {
|
||||
|
||||
BrowserWindow.fromWebContents = (webContents) => {
|
||||
for (const window of BrowserWindow.getAllWindows()) {
|
||||
if (window.webContents && window.webContents.equal(webContents)) return window
|
||||
if (window.webContents.equal(webContents)) return window
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
BrowserWindow.fromBrowserView = (browserView) => {
|
||||
|
||||
@@ -4,15 +4,29 @@ const { app, BrowserWindow, deprecate } = require('electron')
|
||||
const binding = process.electronBinding('dialog')
|
||||
const v8Util = process.electronBinding('v8_util')
|
||||
|
||||
const fileDialogProperties = {
|
||||
const DialogType = {
|
||||
OPEN: 'OPEN',
|
||||
SAVE: 'SAVE'
|
||||
}
|
||||
|
||||
const saveFileDialogProperties = {
|
||||
createDirectory: 1 << 0,
|
||||
showHiddenFiles: 1 << 1,
|
||||
treatPackageAsDirectory: 1 << 2,
|
||||
showOverwriteConfirmation: 1 << 3,
|
||||
dontAddToRecent: 1 << 4
|
||||
}
|
||||
|
||||
const openFileDialogProperties = {
|
||||
openFile: 1 << 0,
|
||||
openDirectory: 1 << 1,
|
||||
multiSelections: 1 << 2,
|
||||
createDirectory: 1 << 3,
|
||||
createDirectory: 1 << 3, // macOS
|
||||
showHiddenFiles: 1 << 4,
|
||||
promptToCreate: 1 << 5,
|
||||
noResolveAliases: 1 << 6,
|
||||
treatPackageAsDirectory: 1 << 7
|
||||
promptToCreate: 1 << 5, // Windows
|
||||
noResolveAliases: 1 << 6, // macOS
|
||||
treatPackageAsDirectory: 1 << 7, // macOS
|
||||
dontAddToRecent: 1 << 8 // Windows
|
||||
}
|
||||
|
||||
const normalizeAccessKey = (text) => {
|
||||
@@ -44,6 +58,18 @@ const checkAppInitialized = function () {
|
||||
}
|
||||
}
|
||||
|
||||
const setupDialogProperties = (type, properties) => {
|
||||
const dialogPropertiesTypes = (type === DialogType.OPEN) ? openFileDialogProperties : saveFileDialogProperties
|
||||
let dialogProperties = 0
|
||||
for (const prop in dialogPropertiesTypes) {
|
||||
if (properties.includes(prop)) {
|
||||
dialogProperties |= dialogPropertiesTypes[prop]
|
||||
}
|
||||
}
|
||||
|
||||
return dialogProperties
|
||||
}
|
||||
|
||||
const saveDialog = (sync, window, options) => {
|
||||
checkAppInitialized()
|
||||
|
||||
@@ -58,6 +84,7 @@ const saveDialog = (sync, window, options) => {
|
||||
buttonLabel = '',
|
||||
defaultPath = '',
|
||||
filters = [],
|
||||
properties = [],
|
||||
title = '',
|
||||
message = '',
|
||||
securityScopedBookmarks = false,
|
||||
@@ -72,6 +99,8 @@ const saveDialog = (sync, window, options) => {
|
||||
if (typeof nameFieldLabel !== 'string') throw new TypeError('Name field label must be a string')
|
||||
|
||||
const settings = { buttonLabel, defaultPath, filters, title, message, securityScopedBookmarks, nameFieldLabel, showsTagField, window }
|
||||
settings.properties = setupDialogProperties(DialogType.SAVE, properties)
|
||||
|
||||
return (sync) ? binding.showSaveDialogSync(settings) : binding.showSaveDialog(settings)
|
||||
}
|
||||
|
||||
@@ -102,20 +131,13 @@ const openDialog = (sync, window, options) => {
|
||||
|
||||
if (!Array.isArray(properties)) throw new TypeError('Properties must be an array')
|
||||
|
||||
let dialogProperties = 0
|
||||
for (const prop in fileDialogProperties) {
|
||||
if (properties.includes(prop)) {
|
||||
dialogProperties |= fileDialogProperties[prop]
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof title !== 'string') throw new TypeError('Title must be a string')
|
||||
if (typeof buttonLabel !== 'string') throw new TypeError('Button label must be a string')
|
||||
if (typeof defaultPath !== 'string') throw new TypeError('Default path must be a string')
|
||||
if (typeof message !== 'string') throw new TypeError('Message must be a string')
|
||||
|
||||
const settings = { title, buttonLabel, defaultPath, filters, message, securityScopedBookmarks, window }
|
||||
settings.properties = dialogProperties
|
||||
settings.properties = setupDialogProperties(DialogType.OPEN, properties)
|
||||
|
||||
return (sync) ? binding.showOpenDialogSync(settings) : binding.showOpenDialog(settings)
|
||||
}
|
||||
@@ -141,7 +163,6 @@ const messageBox = (sync, window, options) => {
|
||||
defaultId = -1,
|
||||
detail = '',
|
||||
icon = null,
|
||||
noLink = false,
|
||||
message = '',
|
||||
title = '',
|
||||
type = 'none'
|
||||
@@ -152,15 +173,11 @@ const messageBox = (sync, window, options) => {
|
||||
if (!Array.isArray(buttons)) throw new TypeError('Buttons must be an array')
|
||||
if (options.normalizeAccessKeys) buttons = buttons.map(normalizeAccessKey)
|
||||
if (typeof title !== 'string') throw new TypeError('Title must be a string')
|
||||
if (typeof noLink !== 'boolean') throw new TypeError('noLink must be a boolean')
|
||||
if (typeof message !== 'string') throw new TypeError('Message must be a string')
|
||||
if (typeof detail !== 'string') throw new TypeError('Detail must be a string')
|
||||
if (typeof checkboxLabel !== 'string') throw new TypeError('checkboxLabel must be a string')
|
||||
|
||||
checkboxChecked = !!checkboxChecked
|
||||
if (checkboxChecked && !checkboxLabel) {
|
||||
throw new Error('checkboxChecked requires that checkboxLabel also be passed')
|
||||
}
|
||||
|
||||
// Choose a default button to get selected when dialog is cancelled.
|
||||
if (cancelId == null) {
|
||||
@@ -175,13 +192,15 @@ const messageBox = (sync, window, options) => {
|
||||
}
|
||||
}
|
||||
|
||||
const flags = options.noLink ? messageBoxOptions.noLink : 0
|
||||
|
||||
const settings = {
|
||||
window,
|
||||
messageBoxType,
|
||||
buttons,
|
||||
defaultId,
|
||||
cancelId,
|
||||
noLink,
|
||||
flags,
|
||||
title,
|
||||
message,
|
||||
detail,
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const common = require('@electron/internal/common/api/exports/electron')
|
||||
// since browser module list is also used in renderer, keep it separate.
|
||||
const moduleList = require('@electron/internal/browser/api/module-list')
|
||||
|
||||
// Import common modules.
|
||||
common.defineProperties(exports)
|
||||
|
||||
for (const module of moduleList) {
|
||||
Object.defineProperty(exports, module.name, {
|
||||
enumerable: !module.private,
|
||||
get: common.handleESModule(module.loader)
|
||||
})
|
||||
}
|
||||
6
lib/browser/api/exports/electron.ts
Normal file
6
lib/browser/api/exports/electron.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { defineProperties } from '@electron/internal/common/define-properties'
|
||||
import { commonModuleList } from '@electron/internal/common/api/module-list'
|
||||
import { browserModuleList } from '@electron/internal/browser/api/module-list'
|
||||
|
||||
defineProperties(exports, commonModuleList)
|
||||
defineProperties(exports, browserModuleList)
|
||||
@@ -1,38 +1,6 @@
|
||||
import { EventEmitter } from 'events'
|
||||
import { IpcMainInvokeEvent } from 'electron'
|
||||
import { IpcMainImpl } from '@electron/internal/browser/ipc-main-impl'
|
||||
|
||||
class IpcMain extends EventEmitter {
|
||||
private _invokeHandlers: Map<string, (e: IpcMainInvokeEvent, ...args: any[]) => void> = new Map();
|
||||
|
||||
handle: Electron.IpcMain['handle'] = (method, fn) => {
|
||||
if (this._invokeHandlers.has(method)) {
|
||||
throw new Error(`Attempted to register a second handler for '${method}'`)
|
||||
}
|
||||
if (typeof fn !== 'function') {
|
||||
throw new Error(`Expected handler to be a function, but found type '${typeof fn}'`)
|
||||
}
|
||||
this._invokeHandlers.set(method, async (e, ...args) => {
|
||||
try {
|
||||
(e as any)._reply(await Promise.resolve(fn(e, ...args)))
|
||||
} catch (err) {
|
||||
(e as any)._throw(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
handleOnce: Electron.IpcMain['handleOnce'] = (method, fn) => {
|
||||
this.handle(method, (e, ...args) => {
|
||||
this.removeHandler(method)
|
||||
return fn(e, ...args)
|
||||
})
|
||||
}
|
||||
|
||||
removeHandler (method: string) {
|
||||
this._invokeHandlers.delete(method)
|
||||
}
|
||||
}
|
||||
|
||||
const ipcMain = new IpcMain()
|
||||
const ipcMain = new IpcMainImpl()
|
||||
|
||||
// Do not throw exception when channel name is "error".
|
||||
ipcMain.on('error', () => {})
|
||||
|
||||
@@ -21,7 +21,6 @@ module.exports = [
|
||||
{ name: 'inAppPurchase' },
|
||||
{ name: 'Menu' },
|
||||
{ name: 'MenuItem' },
|
||||
{ name: 'nativeTheme' },
|
||||
{ name: 'net' },
|
||||
{ name: 'netLog' },
|
||||
{ name: 'Notification' },
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
'use strict'
|
||||
|
||||
// TODO: Updating this file also required updating the module-keys file
|
||||
|
||||
const features = process.electronBinding('features')
|
||||
|
||||
// Browser side modules, please sort alphabetically.
|
||||
module.exports = [
|
||||
export const browserModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'app', loader: () => require('./app') },
|
||||
{ name: 'autoUpdater', loader: () => require('./auto-updater') },
|
||||
{ name: 'BrowserView', loader: () => require('./browser-view') },
|
||||
@@ -37,7 +35,7 @@ module.exports = [
|
||||
]
|
||||
|
||||
if (features.isViewApiEnabled()) {
|
||||
module.exports.push(
|
||||
browserModuleList.push(
|
||||
{ name: 'BoxLayout', loader: () => require('./views/box-layout') },
|
||||
{ name: 'Button', loader: () => require('./views/button') },
|
||||
{ name: 'LabelButton', loader: () => require('./views/label-button') },
|
||||
@@ -2,13 +2,17 @@
|
||||
|
||||
const url = require('url')
|
||||
const { EventEmitter } = require('events')
|
||||
const { Readable, Writable } = require('stream')
|
||||
const { Readable } = require('stream')
|
||||
const { app } = require('electron')
|
||||
const { Session } = process.electronBinding('session')
|
||||
const { net, Net, _isValidHeaderName, _isValidHeaderValue } = process.electronBinding('net')
|
||||
const { URLLoader } = net
|
||||
const { net, Net } = process.electronBinding('net')
|
||||
const { URLRequest } = net
|
||||
|
||||
Object.setPrototypeOf(URLLoader.prototype, EventEmitter.prototype)
|
||||
// Net is an EventEmitter.
|
||||
Object.setPrototypeOf(Net.prototype, EventEmitter.prototype)
|
||||
EventEmitter.call(net)
|
||||
|
||||
Object.setPrototypeOf(URLRequest.prototype, EventEmitter.prototype)
|
||||
|
||||
const kSupportedProtocols = new Set(['http:', 'https:'])
|
||||
|
||||
@@ -36,44 +40,43 @@ const discardableDuplicateHeaders = new Set([
|
||||
])
|
||||
|
||||
class IncomingMessage extends Readable {
|
||||
constructor (responseHead) {
|
||||
constructor (urlRequest) {
|
||||
super()
|
||||
this._shouldPush = false
|
||||
this._data = []
|
||||
this._responseHead = responseHead
|
||||
this.urlRequest = urlRequest
|
||||
this.shouldPush = false
|
||||
this.data = []
|
||||
this.urlRequest.on('data', (event, chunk) => {
|
||||
this._storeInternalData(chunk)
|
||||
this._pushInternalData()
|
||||
})
|
||||
this.urlRequest.on('end', () => {
|
||||
this._storeInternalData(null)
|
||||
this._pushInternalData()
|
||||
})
|
||||
}
|
||||
|
||||
get statusCode () {
|
||||
return this._responseHead.statusCode
|
||||
return this.urlRequest.statusCode
|
||||
}
|
||||
|
||||
get statusMessage () {
|
||||
return this._responseHead.statusMessage
|
||||
return this.urlRequest.statusMessage
|
||||
}
|
||||
|
||||
get headers () {
|
||||
const filteredHeaders = {}
|
||||
const { rawHeaders } = this._responseHead
|
||||
rawHeaders.forEach(header => {
|
||||
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key) &&
|
||||
discardableDuplicateHeaders.has(header.key)) {
|
||||
const rawHeaders = this.urlRequest.rawResponseHeaders
|
||||
Object.keys(rawHeaders).forEach(header => {
|
||||
if (header in filteredHeaders && discardableDuplicateHeaders.has(header)) {
|
||||
// do nothing with discardable duplicate headers
|
||||
} else {
|
||||
if (header.key === 'set-cookie') {
|
||||
if (header === 'set-cookie') {
|
||||
// keep set-cookie as an array per Node.js rules
|
||||
// see https://nodejs.org/api/http.html#http_message_headers
|
||||
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
|
||||
filteredHeaders[header.key].push(header.value)
|
||||
} else {
|
||||
filteredHeaders[header.key] = [header.value]
|
||||
}
|
||||
filteredHeaders[header] = rawHeaders[header]
|
||||
} else {
|
||||
// for non-cookie headers, the values are joined together with ', '
|
||||
if (Object.prototype.hasOwnProperty.call(filteredHeaders, header.key)) {
|
||||
filteredHeaders[header.key] += `, ${header.value}`
|
||||
} else {
|
||||
filteredHeaders[header.key] = header.value
|
||||
}
|
||||
filteredHeaders[header] = rawHeaders[header].join(', ')
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -85,11 +88,11 @@ class IncomingMessage extends Readable {
|
||||
}
|
||||
|
||||
get httpVersionMajor () {
|
||||
return this._responseHead.httpVersion.major
|
||||
return this.urlRequest.httpVersionMajor
|
||||
}
|
||||
|
||||
get httpVersionMinor () {
|
||||
return this._responseHead.httpVersion.minor
|
||||
return this.urlRequest.httpVersionMinor
|
||||
}
|
||||
|
||||
get rawTrailers () {
|
||||
@@ -101,197 +104,181 @@ class IncomingMessage extends Readable {
|
||||
}
|
||||
|
||||
_storeInternalData (chunk) {
|
||||
this._data.push(chunk)
|
||||
this._pushInternalData()
|
||||
this.data.push(chunk)
|
||||
}
|
||||
|
||||
_pushInternalData () {
|
||||
while (this._shouldPush && this._data.length > 0) {
|
||||
const chunk = this._data.shift()
|
||||
this._shouldPush = this.push(chunk)
|
||||
while (this.shouldPush && this.data.length > 0) {
|
||||
const chunk = this.data.shift()
|
||||
this.shouldPush = this.push(chunk)
|
||||
}
|
||||
}
|
||||
|
||||
_read () {
|
||||
this._shouldPush = true
|
||||
this.shouldPush = true
|
||||
this._pushInternalData()
|
||||
}
|
||||
}
|
||||
|
||||
/** Writable stream that buffers up everything written to it. */
|
||||
class SlurpStream extends Writable {
|
||||
constructor () {
|
||||
super()
|
||||
this._data = Buffer.alloc(0)
|
||||
}
|
||||
_write (chunk, encoding, callback) {
|
||||
this._data = Buffer.concat([this._data, chunk])
|
||||
callback()
|
||||
}
|
||||
data () { return this._data }
|
||||
}
|
||||
|
||||
class ChunkedBodyStream extends Writable {
|
||||
constructor (clientRequest) {
|
||||
super()
|
||||
this._clientRequest = clientRequest
|
||||
}
|
||||
|
||||
_write (chunk, encoding, callback) {
|
||||
if (this._downstream) {
|
||||
this._downstream.write(chunk).then(callback, callback)
|
||||
} else {
|
||||
// the contract of _write is that we won't be called again until we call
|
||||
// the callback, so we're good to just save a single chunk.
|
||||
this._pendingChunk = chunk
|
||||
this._pendingCallback = callback
|
||||
|
||||
// The first write to a chunked body stream begins the request.
|
||||
this._clientRequest._startRequest()
|
||||
}
|
||||
}
|
||||
|
||||
_final (callback) {
|
||||
this._downstream.done()
|
||||
callback()
|
||||
}
|
||||
|
||||
startReading (pipe) {
|
||||
if (this._downstream) {
|
||||
throw new Error('two startReading calls???')
|
||||
}
|
||||
this._downstream = pipe
|
||||
if (this._pendingChunk) {
|
||||
const doneWriting = (maybeError) => {
|
||||
const cb = this._pendingCallback
|
||||
delete this._pendingCallback
|
||||
delete this._pendingChunk
|
||||
cb(maybeError)
|
||||
}
|
||||
this._downstream.write(this._pendingChunk).then(doneWriting, doneWriting)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseOptions (options) {
|
||||
if (typeof options === 'string') {
|
||||
options = url.parse(options)
|
||||
URLRequest.prototype._emitRequestEvent = function (isAsync, ...rest) {
|
||||
if (isAsync) {
|
||||
process.nextTick(() => {
|
||||
this.clientRequest.emit(...rest)
|
||||
})
|
||||
} else {
|
||||
options = { ...options }
|
||||
this.clientRequest.emit(...rest)
|
||||
}
|
||||
|
||||
const method = (options.method || 'GET').toUpperCase()
|
||||
let urlStr = options.url
|
||||
|
||||
if (!urlStr) {
|
||||
const urlObj = {}
|
||||
const protocol = options.protocol || 'http:'
|
||||
if (!kSupportedProtocols.has(protocol)) {
|
||||
throw new Error('Protocol "' + protocol + '" not supported')
|
||||
}
|
||||
urlObj.protocol = protocol
|
||||
|
||||
if (options.host) {
|
||||
urlObj.host = options.host
|
||||
} else {
|
||||
if (options.hostname) {
|
||||
urlObj.hostname = options.hostname
|
||||
} else {
|
||||
urlObj.hostname = 'localhost'
|
||||
}
|
||||
|
||||
if (options.port) {
|
||||
urlObj.port = options.port
|
||||
}
|
||||
}
|
||||
|
||||
if (options.path && / /.test(options.path)) {
|
||||
// The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
|
||||
// with an additional rule for ignoring percentage-escaped characters
|
||||
// but that's a) hard to capture in a regular expression that performs
|
||||
// well, and b) possibly too restrictive for real-world usage. That's
|
||||
// why it only scans for spaces because those are guaranteed to create
|
||||
// an invalid request.
|
||||
throw new TypeError('Request path contains unescaped characters')
|
||||
}
|
||||
const pathObj = url.parse(options.path || '/')
|
||||
urlObj.pathname = pathObj.pathname
|
||||
urlObj.search = pathObj.search
|
||||
urlObj.hash = pathObj.hash
|
||||
urlStr = url.format(urlObj)
|
||||
}
|
||||
|
||||
const redirectPolicy = options.redirect || 'follow'
|
||||
if (!['follow', 'error', 'manual'].includes(redirectPolicy)) {
|
||||
throw new Error('redirect mode should be one of follow, error or manual')
|
||||
}
|
||||
|
||||
if (options.headers != null && typeof options.headers !== 'object') {
|
||||
throw new TypeError('headers must be an object')
|
||||
}
|
||||
|
||||
const urlLoaderOptions = {
|
||||
method: method,
|
||||
url: urlStr,
|
||||
redirectPolicy,
|
||||
extraHeaders: options.headers || {}
|
||||
}
|
||||
for (const [name, value] of Object.entries(urlLoaderOptions.extraHeaders)) {
|
||||
if (!_isValidHeaderName(name)) {
|
||||
throw new Error(`Invalid header name: '${name}'`)
|
||||
}
|
||||
if (!_isValidHeaderValue(value.toString())) {
|
||||
throw new Error(`Invalid value for header '${name}': '${value}'`)
|
||||
}
|
||||
}
|
||||
if (options.session) {
|
||||
if (options.session instanceof Session) {
|
||||
urlLoaderOptions.session = options.session
|
||||
} else {
|
||||
throw new TypeError('`session` should be an instance of the Session class')
|
||||
}
|
||||
} else if (options.partition) {
|
||||
if (typeof options.partition === 'string') {
|
||||
urlLoaderOptions.partition = options.partition
|
||||
} else {
|
||||
throw new TypeError('`partition` should be a string')
|
||||
}
|
||||
}
|
||||
return urlLoaderOptions
|
||||
}
|
||||
|
||||
class ClientRequest extends Writable {
|
||||
URLRequest.prototype._emitResponseEvent = function (isAsync, ...rest) {
|
||||
if (isAsync) {
|
||||
process.nextTick(() => {
|
||||
this._response.emit(...rest)
|
||||
})
|
||||
} else {
|
||||
this._response.emit(...rest)
|
||||
}
|
||||
}
|
||||
|
||||
class ClientRequest extends EventEmitter {
|
||||
constructor (options, callback) {
|
||||
super({ autoDestroy: true })
|
||||
super()
|
||||
|
||||
if (!app.isReady()) {
|
||||
throw new Error('net module can only be used after app is ready')
|
||||
}
|
||||
|
||||
if (typeof options === 'string') {
|
||||
options = url.parse(options)
|
||||
} else {
|
||||
options = Object.assign({}, options)
|
||||
}
|
||||
|
||||
const method = (options.method || 'GET').toUpperCase()
|
||||
let urlStr = options.url
|
||||
|
||||
if (!urlStr) {
|
||||
const urlObj = {}
|
||||
const protocol = options.protocol || 'http:'
|
||||
if (!kSupportedProtocols.has(protocol)) {
|
||||
throw new Error('Protocol "' + protocol + '" not supported')
|
||||
}
|
||||
urlObj.protocol = protocol
|
||||
|
||||
if (options.host) {
|
||||
urlObj.host = options.host
|
||||
} else {
|
||||
if (options.hostname) {
|
||||
urlObj.hostname = options.hostname
|
||||
} else {
|
||||
urlObj.hostname = 'localhost'
|
||||
}
|
||||
|
||||
if (options.port) {
|
||||
urlObj.port = options.port
|
||||
}
|
||||
}
|
||||
|
||||
if (options.path && / /.test(options.path)) {
|
||||
// The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
|
||||
// with an additional rule for ignoring percentage-escaped characters
|
||||
// but that's a) hard to capture in a regular expression that performs
|
||||
// well, and b) possibly too restrictive for real-world usage. That's
|
||||
// why it only scans for spaces because those are guaranteed to create
|
||||
// an invalid request.
|
||||
throw new TypeError('Request path contains unescaped characters')
|
||||
}
|
||||
const pathObj = url.parse(options.path || '/')
|
||||
urlObj.pathname = pathObj.pathname
|
||||
urlObj.search = pathObj.search
|
||||
urlObj.hash = pathObj.hash
|
||||
urlStr = url.format(urlObj)
|
||||
}
|
||||
|
||||
const redirectPolicy = options.redirect || 'follow'
|
||||
if (!['follow', 'error', 'manual'].includes(redirectPolicy)) {
|
||||
throw new Error('redirect mode should be one of follow, error or manual')
|
||||
}
|
||||
|
||||
const urlRequestOptions = {
|
||||
method: method,
|
||||
url: urlStr,
|
||||
redirect: redirectPolicy
|
||||
}
|
||||
if (options.session) {
|
||||
if (options.session instanceof Session) {
|
||||
urlRequestOptions.session = options.session
|
||||
} else {
|
||||
throw new TypeError('`session` should be an instance of the Session class')
|
||||
}
|
||||
} else if (options.partition) {
|
||||
if (typeof options.partition === 'string') {
|
||||
urlRequestOptions.partition = options.partition
|
||||
} else {
|
||||
throw new TypeError('`partition` should be a string')
|
||||
}
|
||||
}
|
||||
|
||||
const urlRequest = new URLRequest(urlRequestOptions)
|
||||
|
||||
// Set back and forward links.
|
||||
this.urlRequest = urlRequest
|
||||
urlRequest.clientRequest = this
|
||||
|
||||
// This is a copy of the extra headers structure held by the native
|
||||
// net::URLRequest. The main reason is to keep the getHeader API synchronous
|
||||
// after the request starts.
|
||||
this.extraHeaders = {}
|
||||
|
||||
if (options.headers) {
|
||||
for (const key in options.headers) {
|
||||
this.setHeader(key, options.headers[key])
|
||||
}
|
||||
}
|
||||
|
||||
// Set when the request uses chunked encoding. Can be switched
|
||||
// to true only once and never set back to false.
|
||||
this.chunkedEncodingEnabled = false
|
||||
|
||||
urlRequest.on('response', () => {
|
||||
const response = new IncomingMessage(urlRequest)
|
||||
urlRequest._response = response
|
||||
this.emit('response', response)
|
||||
})
|
||||
|
||||
urlRequest.on('login', (event, authInfo, callback) => {
|
||||
this.emit('login', authInfo, (username, password) => {
|
||||
// If null or undefined username/password, force to empty string.
|
||||
if (username === null || username === undefined) {
|
||||
username = ''
|
||||
}
|
||||
if (typeof username !== 'string') {
|
||||
throw new Error('username must be a string')
|
||||
}
|
||||
if (password === null || password === undefined) {
|
||||
password = ''
|
||||
}
|
||||
if (typeof password !== 'string') {
|
||||
throw new Error('password must be a string')
|
||||
}
|
||||
callback(username, password)
|
||||
})
|
||||
})
|
||||
|
||||
if (callback) {
|
||||
this.once('response', callback)
|
||||
}
|
||||
}
|
||||
|
||||
const { redirectPolicy, ...urlLoaderOptions } = parseOptions(options)
|
||||
this._urlLoaderOptions = urlLoaderOptions
|
||||
this._redirectPolicy = redirectPolicy
|
||||
this._started = false
|
||||
get chunkedEncoding () {
|
||||
return this.chunkedEncodingEnabled
|
||||
}
|
||||
|
||||
set chunkedEncoding (value) {
|
||||
if (this._started) {
|
||||
throw new Error('chunkedEncoding can only be set before the request is started')
|
||||
}
|
||||
if (typeof this._chunkedEncoding !== 'undefined') {
|
||||
throw new Error('chunkedEncoding can only be set once')
|
||||
}
|
||||
this._chunkedEncoding = !!value
|
||||
if (this._chunkedEncoding) {
|
||||
this._body = new ChunkedBodyStream(this)
|
||||
this._urlLoaderOptions.body = (pipe) => {
|
||||
this._body.startReading(pipe)
|
||||
}
|
||||
if (!this.urlRequest.notStarted) {
|
||||
throw new Error('Can\'t set the transfer encoding, headers have been sent')
|
||||
}
|
||||
this.chunkedEncodingEnabled = value
|
||||
}
|
||||
|
||||
setHeader (name, value) {
|
||||
@@ -301,18 +288,13 @@ class ClientRequest extends Writable {
|
||||
if (value == null) {
|
||||
throw new Error('`value` required in setHeader("' + name + '", value)')
|
||||
}
|
||||
if (this._started || this._firstWrite) {
|
||||
if (!this.urlRequest.notStarted) {
|
||||
throw new Error('Can\'t set headers after they are sent')
|
||||
}
|
||||
if (!_isValidHeaderName(name)) {
|
||||
throw new Error(`Invalid header name: '${name}'`)
|
||||
}
|
||||
if (!_isValidHeaderValue(value.toString())) {
|
||||
throw new Error(`Invalid value for header '${name}': '${value}'`)
|
||||
}
|
||||
|
||||
const key = name.toLowerCase()
|
||||
this._urlLoaderOptions.extraHeaders[key] = value
|
||||
this.extraHeaders[key] = value
|
||||
this.urlRequest.setExtraHeader(name, value.toString())
|
||||
}
|
||||
|
||||
getHeader (name) {
|
||||
@@ -320,8 +302,12 @@ class ClientRequest extends Writable {
|
||||
throw new Error('`name` is required for getHeader(name)')
|
||||
}
|
||||
|
||||
if (!this.extraHeaders) {
|
||||
return
|
||||
}
|
||||
|
||||
const key = name.toLowerCase()
|
||||
return this._urlLoaderOptions.extraHeaders[key]
|
||||
return this.extraHeaders[key]
|
||||
}
|
||||
|
||||
removeHeader (name) {
|
||||
@@ -329,144 +315,93 @@ class ClientRequest extends Writable {
|
||||
throw new Error('`name` is required for removeHeader(name)')
|
||||
}
|
||||
|
||||
if (this._started || this._firstWrite) {
|
||||
if (!this.urlRequest.notStarted) {
|
||||
throw new Error('Can\'t remove headers after they are sent')
|
||||
}
|
||||
|
||||
const key = name.toLowerCase()
|
||||
delete this._urlLoaderOptions.extraHeaders[key]
|
||||
delete this.extraHeaders[key]
|
||||
this.urlRequest.removeExtraHeader(name)
|
||||
}
|
||||
|
||||
_write (chunk, encoding, callback) {
|
||||
this._firstWrite = true
|
||||
if (!this._body) {
|
||||
this._body = new SlurpStream()
|
||||
this._body.on('finish', () => {
|
||||
this._urlLoaderOptions.body = this._body.data()
|
||||
this._startRequest()
|
||||
})
|
||||
_write (chunk, encoding, callback, isLast) {
|
||||
const chunkIsString = typeof chunk === 'string'
|
||||
const chunkIsBuffer = chunk instanceof Buffer
|
||||
if (!chunkIsString && !chunkIsBuffer) {
|
||||
throw new TypeError('First argument must be a string or Buffer')
|
||||
}
|
||||
// TODO: is this the right way to forward to another stream?
|
||||
this._body.write(chunk, encoding, callback)
|
||||
|
||||
if (chunkIsString) {
|
||||
// We convert all strings into binary buffers.
|
||||
chunk = Buffer.from(chunk, encoding)
|
||||
}
|
||||
|
||||
// Since writing to the network is asynchronous, we conservatively
|
||||
// assume that request headers are written after delivering the first
|
||||
// buffer to the network IO thread.
|
||||
if (this.urlRequest.notStarted) {
|
||||
this.urlRequest.setChunkedUpload(this.chunkedEncoding)
|
||||
}
|
||||
|
||||
// Headers are assumed to be sent on first call to _writeBuffer,
|
||||
// i.e. after the first call to write or end.
|
||||
const result = this.urlRequest.write(chunk, isLast)
|
||||
|
||||
// The write callback is fired asynchronously to mimic Node.js.
|
||||
if (callback) {
|
||||
process.nextTick(callback)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
_final (callback) {
|
||||
if (this._body) {
|
||||
// TODO: is this the right way to forward to another stream?
|
||||
this._body.end(callback)
|
||||
} else {
|
||||
// end() called without a body, go ahead and start the request
|
||||
this._startRequest()
|
||||
callback()
|
||||
write (data, encoding, callback) {
|
||||
if (this.urlRequest.finished) {
|
||||
const error = new Error('Write after end')
|
||||
process.nextTick(writeAfterEndNT, this, error, callback)
|
||||
return true
|
||||
}
|
||||
|
||||
return this._write(data, encoding, callback, false)
|
||||
}
|
||||
|
||||
_startRequest () {
|
||||
this._started = true
|
||||
const stringifyValues = (obj) => {
|
||||
const ret = {}
|
||||
for (const k in obj) {
|
||||
ret[k] = obj[k].toString()
|
||||
}
|
||||
return ret
|
||||
end (data, encoding, callback) {
|
||||
if (this.urlRequest.finished) {
|
||||
return false
|
||||
}
|
||||
const opts = { ...this._urlLoaderOptions, extraHeaders: stringifyValues(this._urlLoaderOptions.extraHeaders) }
|
||||
this._urlLoader = new URLLoader(opts)
|
||||
this._urlLoader.on('response-started', (event, finalUrl, responseHead) => {
|
||||
const response = this._response = new IncomingMessage(responseHead)
|
||||
this.emit('response', response)
|
||||
})
|
||||
this._urlLoader.on('data', (event, data) => {
|
||||
this._response._storeInternalData(Buffer.from(data))
|
||||
})
|
||||
this._urlLoader.on('complete', () => {
|
||||
if (this._response) { this._response._storeInternalData(null) }
|
||||
})
|
||||
this._urlLoader.on('error', (event, netErrorString) => {
|
||||
const error = new Error(netErrorString)
|
||||
if (this._response) this._response.destroy(error)
|
||||
this._die(error)
|
||||
})
|
||||
|
||||
this._urlLoader.on('login', (event, authInfo, callback) => {
|
||||
const handled = this.emit('login', authInfo, callback)
|
||||
if (!handled) {
|
||||
// If there were no listeners, cancel the authentication request.
|
||||
callback()
|
||||
}
|
||||
})
|
||||
if (typeof data === 'function') {
|
||||
callback = data
|
||||
encoding = null
|
||||
data = null
|
||||
} else if (typeof encoding === 'function') {
|
||||
callback = encoding
|
||||
encoding = null
|
||||
}
|
||||
|
||||
this._urlLoader.on('redirect', (event, redirectInfo, headers) => {
|
||||
const { statusCode, newMethod, newUrl } = redirectInfo
|
||||
if (this._redirectPolicy === 'error') {
|
||||
this._die(new Error(`Attempted to redirect, but redirect policy was 'error'`))
|
||||
} else if (this._redirectPolicy === 'manual') {
|
||||
let _followRedirect = false
|
||||
this._followRedirectCb = () => { _followRedirect = true }
|
||||
try {
|
||||
this.emit('redirect', statusCode, newMethod, newUrl, headers)
|
||||
} finally {
|
||||
this._followRedirectCb = null
|
||||
if (!_followRedirect && !this._aborted) {
|
||||
this._die(new Error('Redirect was cancelled'))
|
||||
}
|
||||
}
|
||||
} else if (this._redirectPolicy === 'follow') {
|
||||
// Calling followRedirect() when the redirect policy is 'follow' is
|
||||
// allowed but does nothing. (Perhaps it should throw an error
|
||||
// though...? Since the redirect will happen regardless.)
|
||||
try {
|
||||
this._followRedirectCb = () => {}
|
||||
this.emit('redirect', statusCode, newMethod, newUrl, headers)
|
||||
} finally {
|
||||
this._followRedirectCb = null
|
||||
}
|
||||
} else {
|
||||
this._die(new Error(`Unexpected redirect policy '${this._redirectPolicy}'`))
|
||||
}
|
||||
})
|
||||
data = data || ''
|
||||
|
||||
this._urlLoader.on('upload-progress', (event, position, total) => {
|
||||
this._uploadProgress = { active: true, started: true, current: position, total }
|
||||
this.emit('upload-progress', position, total) // Undocumented, for now
|
||||
})
|
||||
|
||||
this._urlLoader.on('download-progress', (event, current) => {
|
||||
if (this._response) {
|
||||
this._response.emit('download-progress', current) // Undocumented, for now
|
||||
}
|
||||
})
|
||||
return this._write(data, encoding, callback, true)
|
||||
}
|
||||
|
||||
followRedirect () {
|
||||
if (this._followRedirectCb) {
|
||||
this._followRedirectCb()
|
||||
} else {
|
||||
throw new Error('followRedirect() called, but was not waiting for a redirect')
|
||||
}
|
||||
this.urlRequest.followRedirect()
|
||||
}
|
||||
|
||||
abort () {
|
||||
if (!this._aborted) {
|
||||
process.nextTick(() => { this.emit('abort') })
|
||||
}
|
||||
this._aborted = true
|
||||
this._die()
|
||||
}
|
||||
|
||||
_die (err) {
|
||||
this.destroy(err)
|
||||
if (this._urlLoader) {
|
||||
this._urlLoader.cancel()
|
||||
if (this._response) this._response.destroy(err)
|
||||
}
|
||||
this.urlRequest.cancel()
|
||||
}
|
||||
|
||||
getUploadProgress () {
|
||||
return this._uploadProgress ? { ...this._uploadProgress } : { active: false }
|
||||
return this.urlRequest.getUploadProgress()
|
||||
}
|
||||
}
|
||||
|
||||
function writeAfterEndNT (self, error, callback) {
|
||||
self.emit('error', error)
|
||||
if (callback) callback(error)
|
||||
}
|
||||
|
||||
Net.prototype.request = function (options, callback) {
|
||||
return new ClientRequest(options, callback)
|
||||
}
|
||||
|
||||
@@ -191,12 +191,12 @@ TouchBar.TouchBarButton = class TouchBarButton extends TouchBarItem {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
this._addImmutableProperty('type', 'button')
|
||||
const { click, icon, iconPosition, label, backgroundColor } = config
|
||||
this._addLiveProperty('label', label)
|
||||
this._addLiveProperty('backgroundColor', backgroundColor)
|
||||
this._addLiveProperty('icon', icon)
|
||||
this._addLiveProperty('iconPosition', iconPosition)
|
||||
if (typeof click === 'function') {
|
||||
this._addLiveProperty('label', config.label)
|
||||
this._addLiveProperty('accessibilityLabel', config.accessibilityLabel)
|
||||
this._addLiveProperty('backgroundColor', config.backgroundColor)
|
||||
this._addLiveProperty('icon', config.icon)
|
||||
this._addLiveProperty('iconPosition', config.iconPosition)
|
||||
if (typeof config.click === 'function') {
|
||||
this._addImmutableProperty('onInteraction', () => {
|
||||
config.click()
|
||||
})
|
||||
@@ -209,14 +209,13 @@ TouchBar.TouchBarColorPicker = class TouchBarColorPicker extends TouchBarItem {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
this._addImmutableProperty('type', 'colorpicker')
|
||||
const { availableColors, change, selectedColor } = config
|
||||
this._addLiveProperty('availableColors', availableColors)
|
||||
this._addLiveProperty('selectedColor', selectedColor)
|
||||
this._addLiveProperty('availableColors', config.availableColors)
|
||||
this._addLiveProperty('selectedColor', config.selectedColor)
|
||||
|
||||
if (typeof change === 'function') {
|
||||
if (typeof config.change === 'function') {
|
||||
this._addImmutableProperty('onInteraction', (details) => {
|
||||
this._selectedColor = details.color
|
||||
change(details.color)
|
||||
config.change(details.color)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -239,6 +238,7 @@ TouchBar.TouchBarLabel = class TouchBarLabel extends TouchBarItem {
|
||||
if (config == null) config = {}
|
||||
this._addImmutableProperty('type', 'label')
|
||||
this._addLiveProperty('label', config.label)
|
||||
this._addLiveProperty('accessibilityLabel', config.accessibilityLabel)
|
||||
this._addLiveProperty('textColor', config.textColor)
|
||||
}
|
||||
}
|
||||
@@ -262,16 +262,15 @@ TouchBar.TouchBarSlider = class TouchBarSlider extends TouchBarItem {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
this._addImmutableProperty('type', 'slider')
|
||||
const { change, label, minValue, maxValue, value } = config
|
||||
this._addLiveProperty('label', label)
|
||||
this._addLiveProperty('minValue', minValue)
|
||||
this._addLiveProperty('maxValue', maxValue)
|
||||
this._addLiveProperty('value', value)
|
||||
this._addLiveProperty('label', config.label)
|
||||
this._addLiveProperty('minValue', config.minValue)
|
||||
this._addLiveProperty('maxValue', config.maxValue)
|
||||
this._addLiveProperty('value', config.value)
|
||||
|
||||
if (typeof change === 'function') {
|
||||
if (typeof config.change === 'function') {
|
||||
this._addImmutableProperty('onInteraction', (details) => {
|
||||
this._value = details.value
|
||||
change(details.value)
|
||||
config.change(details.value)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -290,17 +289,16 @@ TouchBar.TouchBarSegmentedControl = class TouchBarSegmentedControl extends Touch
|
||||
constructor (config) {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
const { segmentStyle, segments, selectedIndex, change, mode } = config
|
||||
this._addImmutableProperty('type', 'segmented_control')
|
||||
this._addLiveProperty('segmentStyle', segmentStyle)
|
||||
this._addLiveProperty('segments', segments || [])
|
||||
this._addLiveProperty('selectedIndex', selectedIndex)
|
||||
this._addLiveProperty('mode', mode)
|
||||
this._addLiveProperty('segmentStyle', config.segmentStyle)
|
||||
this._addLiveProperty('segments', config.segments || [])
|
||||
this._addLiveProperty('selectedIndex', config.selectedIndex)
|
||||
this._addLiveProperty('mode', config.mode)
|
||||
|
||||
if (typeof change === 'function') {
|
||||
if (typeof config.change === 'function') {
|
||||
this._addImmutableProperty('onInteraction', (details) => {
|
||||
this._selectedIndex = details.selectedIndex
|
||||
change(details.selectedIndex, details.isSelected)
|
||||
config.change(details.selectedIndex, details.isSelected)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -310,15 +308,16 @@ TouchBar.TouchBarScrubber = class TouchBarScrubber extends TouchBarItem {
|
||||
constructor (config) {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
const { items, selectedStyle, overlayStyle, showArrowButtons, continuous, mode } = config
|
||||
let { select, highlight } = config
|
||||
this._addImmutableProperty('type', 'scrubber')
|
||||
this._addLiveProperty('items', items)
|
||||
this._addLiveProperty('selectedStyle', selectedStyle || null)
|
||||
this._addLiveProperty('overlayStyle', overlayStyle || null)
|
||||
this._addLiveProperty('showArrowButtons', showArrowButtons || false)
|
||||
this._addLiveProperty('mode', mode || 'free')
|
||||
this._addLiveProperty('continuous', typeof continuous === 'undefined' ? true : continuous)
|
||||
this._addLiveProperty('items', config.items)
|
||||
this._addLiveProperty('selectedStyle', config.selectedStyle || null)
|
||||
this._addLiveProperty('overlayStyle', config.overlayStyle || null)
|
||||
this._addLiveProperty('showArrowButtons', config.showArrowButtons || false)
|
||||
this._addLiveProperty('mode', config.mode || 'free')
|
||||
|
||||
const cont = typeof config.continuous === 'undefined' ? true : config.continuous
|
||||
this._addLiveProperty('continuous', cont)
|
||||
|
||||
if (typeof select === 'function' || typeof highlight === 'function') {
|
||||
if (select == null) select = () => {}
|
||||
|
||||
@@ -7,7 +7,6 @@ const path = require('path')
|
||||
const url = require('url')
|
||||
const { app, ipcMain, session, deprecate } = electron
|
||||
|
||||
const { internalWindowOpen } = require('@electron/internal/browser/guest-window-manager')
|
||||
const NavigationController = require('@electron/internal/browser/navigation-controller')
|
||||
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal')
|
||||
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils')
|
||||
@@ -73,6 +72,7 @@ const defaultPrintingSetting = {
|
||||
headerFooterEnabled: false,
|
||||
marginsType: 0,
|
||||
isFirstRequest: false,
|
||||
requestID: getNextId(),
|
||||
previewUIID: 0,
|
||||
previewModifiable: true,
|
||||
printToPDF: true,
|
||||
@@ -205,10 +205,7 @@ WebContents.prototype.executeJavaScript = function (code, hasUserGesture) {
|
||||
|
||||
// Translate the options of printToPDF.
|
||||
WebContents.prototype.printToPDF = function (options) {
|
||||
const printingSetting = {
|
||||
...defaultPrintingSetting,
|
||||
requestID: getNextId()
|
||||
}
|
||||
const printingSetting = Object.assign({}, defaultPrintingSetting)
|
||||
if (options.landscape) {
|
||||
printingSetting.landscape = options.landscape
|
||||
}
|
||||
@@ -267,7 +264,6 @@ WebContents.prototype.getPrinters = function () {
|
||||
return this._getPrinters()
|
||||
} else {
|
||||
console.error('Error: Printing feature is disabled.')
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,14 +327,15 @@ WebContents.prototype._init = function () {
|
||||
}
|
||||
})
|
||||
|
||||
this.on('-ipc-invoke', function (event, channel, args) {
|
||||
this.on('-ipc-invoke', function (event, internal, channel, args) {
|
||||
event._reply = (result) => event.sendReply({ result })
|
||||
event._throw = (error) => {
|
||||
console.error(`Error occurred in handler for '${channel}':`, error)
|
||||
event.sendReply({ error: error.toString() })
|
||||
}
|
||||
if (ipcMain._invokeHandlers.has(channel)) {
|
||||
ipcMain._invokeHandlers.get(channel)(event, ...args)
|
||||
const target = internal ? ipcMainInternal : ipcMain
|
||||
if (target._invokeHandlers.has(channel)) {
|
||||
target._invokeHandlers.get(channel)(event, ...args)
|
||||
} else {
|
||||
event._throw(`No handler registered for '${channel}'`)
|
||||
}
|
||||
@@ -388,7 +385,9 @@ WebContents.prototype._init = function () {
|
||||
width: 800,
|
||||
height: 600
|
||||
}
|
||||
internalWindowOpen(event, url, referrer, frameName, disposition, options, additionalFeatures, postData)
|
||||
ipcMainInternal.emit('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN',
|
||||
event, url, referrer, frameName, disposition,
|
||||
options, additionalFeatures, postData)
|
||||
})
|
||||
|
||||
// Create a new browser window for the native implementation of
|
||||
@@ -410,14 +409,11 @@ WebContents.prototype._init = function () {
|
||||
webContents
|
||||
}
|
||||
const referrer = { url: '', policy: 'default' }
|
||||
internalWindowOpen(event, url, referrer, frameName, disposition, options)
|
||||
ipcMainInternal.emit('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN',
|
||||
event, url, referrer, frameName, disposition, options)
|
||||
})
|
||||
}
|
||||
|
||||
this.on('login', (event, ...args) => {
|
||||
app.emit('login', event, this, ...args)
|
||||
})
|
||||
|
||||
const event = process.electronBinding('event').createEmpty()
|
||||
app.emit('web-contents-created', event, this)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
'use strict'
|
||||
|
||||
if (process.electronBinding('features').isExtensionsEnabled()) {
|
||||
throw new Error('Attempted to load JS chrome-extension polyfill with //extensions support enabled')
|
||||
}
|
||||
|
||||
const { app, webContents, BrowserWindow } = require('electron')
|
||||
const { getAllWebContents } = process.electronBinding('web_contents')
|
||||
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal')
|
||||
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils')
|
||||
|
||||
const { Buffer } = require('buffer')
|
||||
@@ -156,7 +161,7 @@ const hookWebContentsEvents = function (webContents) {
|
||||
// Handle the chrome.* API messages.
|
||||
let nextId = 0
|
||||
|
||||
ipcMainUtils.handle('CHROME_RUNTIME_CONNECT', function (event, extensionId, connectInfo) {
|
||||
ipcMainUtils.handleSync('CHROME_RUNTIME_CONNECT', function (event, extensionId, connectInfo) {
|
||||
if (isBackgroundPage(event.sender)) {
|
||||
throw new Error('chrome.runtime.connect is not supported in background page')
|
||||
}
|
||||
@@ -178,7 +183,7 @@ ipcMainUtils.handle('CHROME_RUNTIME_CONNECT', function (event, extensionId, conn
|
||||
return { tabId, portId }
|
||||
})
|
||||
|
||||
ipcMainUtils.handle('CHROME_EXTENSION_MANIFEST', function (event, extensionId) {
|
||||
ipcMainUtils.handleSync('CHROME_EXTENSION_MANIFEST', function (event, extensionId) {
|
||||
const manifest = manifestMap[extensionId]
|
||||
if (!manifest) {
|
||||
throw new Error(`Invalid extensionId: ${extensionId}`)
|
||||
@@ -186,7 +191,7 @@ ipcMainUtils.handle('CHROME_EXTENSION_MANIFEST', function (event, extensionId) {
|
||||
return manifest
|
||||
})
|
||||
|
||||
ipcMainUtils.handle('CHROME_RUNTIME_SEND_MESSAGE', async function (event, extensionId, message) {
|
||||
ipcMainInternal.handle('CHROME_RUNTIME_SEND_MESSAGE', async function (event, extensionId, message) {
|
||||
if (isBackgroundPage(event.sender)) {
|
||||
throw new Error('chrome.runtime.sendMessage is not supported in background page')
|
||||
}
|
||||
@@ -199,7 +204,7 @@ ipcMainUtils.handle('CHROME_RUNTIME_SEND_MESSAGE', async function (event, extens
|
||||
return ipcMainUtils.invokeInWebContents(page.webContents, true, `CHROME_RUNTIME_ONMESSAGE_${extensionId}`, event.sender.id, message)
|
||||
})
|
||||
|
||||
ipcMainUtils.handle('CHROME_TABS_SEND_MESSAGE', async function (event, tabId, extensionId, message) {
|
||||
ipcMainInternal.handle('CHROME_TABS_SEND_MESSAGE', async function (event, tabId, extensionId, message) {
|
||||
const contents = webContents.fromId(tabId)
|
||||
if (!contents) {
|
||||
throw new Error(`Sending message to unknown tab ${tabId}`)
|
||||
@@ -233,7 +238,7 @@ const getMessagesPath = (extensionId) => {
|
||||
}
|
||||
}
|
||||
|
||||
ipcMainUtils.handle('CHROME_GET_MESSAGES', async function (event, extensionId) {
|
||||
ipcMainUtils.handleSync('CHROME_GET_MESSAGES', async function (event, extensionId) {
|
||||
const messagesPath = getMessagesPath(extensionId)
|
||||
return fs.promises.readFile(messagesPath)
|
||||
})
|
||||
@@ -252,7 +257,7 @@ const getChromeStoragePath = (storageType, extensionId) => {
|
||||
return path.join(app.getPath('userData'), `/Chrome Storage/${extensionId}-${storageType}.json`)
|
||||
}
|
||||
|
||||
ipcMainUtils.handle('CHROME_STORAGE_READ', async function (event, storageType, extensionId) {
|
||||
ipcMainInternal.handle('CHROME_STORAGE_READ', async function (event, storageType, extensionId) {
|
||||
const filePath = getChromeStoragePath(storageType, extensionId)
|
||||
|
||||
try {
|
||||
@@ -266,7 +271,7 @@ ipcMainUtils.handle('CHROME_STORAGE_READ', async function (event, storageType, e
|
||||
}
|
||||
})
|
||||
|
||||
ipcMainUtils.handle('CHROME_STORAGE_WRITE', async function (event, storageType, extensionId, data) {
|
||||
ipcMainInternal.handle('CHROME_STORAGE_WRITE', async function (event, storageType, extensionId, data) {
|
||||
const filePath = getChromeStoragePath(storageType, extensionId)
|
||||
|
||||
try {
|
||||
@@ -291,7 +296,7 @@ const assertChromeExtension = function (contents, api) {
|
||||
}
|
||||
}
|
||||
|
||||
ipcMainUtils.handle('CHROME_TABS_EXECUTE_SCRIPT', async function (event, tabId, extensionId, details) {
|
||||
ipcMainInternal.handle('CHROME_TABS_EXECUTE_SCRIPT', async function (event, tabId, extensionId, details) {
|
||||
assertChromeExtension(event.sender, 'chrome.tabs.executeScript()')
|
||||
|
||||
const contents = webContents.fromId(tabId)
|
||||
|
||||
@@ -2,7 +2,8 @@ import { dialog, Menu } from 'electron'
|
||||
import * as fs from 'fs'
|
||||
import * as url from 'url'
|
||||
|
||||
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils')
|
||||
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal'
|
||||
import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-utils'
|
||||
|
||||
const convertToMenuTemplate = function (items: ContextMenuItem[], handler: (id: number) => void) {
|
||||
return items.map(function (item) {
|
||||
@@ -59,7 +60,7 @@ const assertChromeDevTools = function (contents: Electron.WebContents, api: stri
|
||||
}
|
||||
}
|
||||
|
||||
ipcMainUtils.handle('ELECTRON_INSPECTOR_CONTEXT_MENU', function (event: Electron.IpcMainEvent, items: ContextMenuItem[], isEditMenu: boolean) {
|
||||
ipcMainInternal.handle('ELECTRON_INSPECTOR_CONTEXT_MENU', function (event: Electron.IpcMainInvokeEvent, items: ContextMenuItem[], isEditMenu: boolean) {
|
||||
return new Promise(resolve => {
|
||||
assertChromeDevTools(event.sender, 'window.InspectorFrontendHost.showContextMenuAtPoint()')
|
||||
|
||||
@@ -71,7 +72,7 @@ ipcMainUtils.handle('ELECTRON_INSPECTOR_CONTEXT_MENU', function (event: Electron
|
||||
})
|
||||
})
|
||||
|
||||
ipcMainUtils.handle('ELECTRON_INSPECTOR_SELECT_FILE', async function (event: Electron.IpcMainEvent) {
|
||||
ipcMainInternal.handle('ELECTRON_INSPECTOR_SELECT_FILE', async function (event: Electron.IpcMainInvokeEvent) {
|
||||
assertChromeDevTools(event.sender, 'window.UI.createFileSelectorElement()')
|
||||
|
||||
const result = await dialog.showOpenDialog({})
|
||||
@@ -83,7 +84,7 @@ ipcMainUtils.handle('ELECTRON_INSPECTOR_SELECT_FILE', async function (event: Ele
|
||||
return [path, data]
|
||||
})
|
||||
|
||||
ipcMainUtils.handle('ELECTRON_INSPECTOR_CONFIRM', async function (event: Electron.IpcMainEvent, message: string = '', title: string = '') {
|
||||
ipcMainUtils.handleSync('ELECTRON_INSPECTOR_CONFIRM', async function (event: Electron.IpcMainInvokeEvent, message: string = '', title: string = '') {
|
||||
assertChromeDevTools(event.sender, 'window.confirm()')
|
||||
|
||||
const options = {
|
||||
|
||||
@@ -5,7 +5,6 @@ const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-interna
|
||||
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils')
|
||||
const parseFeaturesString = require('@electron/internal/common/parse-features-string')
|
||||
const { syncMethods, asyncMethods } = require('@electron/internal/common/web-view-methods')
|
||||
const { serialize } = require('@electron/internal/common/type-utils')
|
||||
|
||||
// Doesn't exist in early initialization.
|
||||
let webViewManager = null
|
||||
@@ -189,7 +188,7 @@ const attachGuest = function (event, embedderFrameId, elementInstanceId, guestIn
|
||||
nodeIntegrationInSubFrames: params.nodeintegrationinsubframes != null ? params.nodeintegrationinsubframes : false,
|
||||
enableRemoteModule: params.enableremotemodule,
|
||||
plugins: params.plugins,
|
||||
zoomFactor: embedder.zoomFactor,
|
||||
zoomFactor: embedder.getZoomFactor(),
|
||||
disablePopups: !params.allowpopups,
|
||||
webSecurity: !params.disablewebsecurity,
|
||||
enableBlinkFeatures: params.blinkfeatures,
|
||||
@@ -313,21 +312,33 @@ const isWebViewTagEnabled = function (contents) {
|
||||
return isWebViewTagEnabledCache.get(contents)
|
||||
}
|
||||
|
||||
const handleMessage = function (channel, handler) {
|
||||
ipcMainUtils.handle(channel, (event, ...args) => {
|
||||
const makeSafeHandler = function (channel, handler) {
|
||||
return (event, ...args) => {
|
||||
if (isWebViewTagEnabled(event.sender)) {
|
||||
return handler(event, ...args)
|
||||
} else {
|
||||
console.error(`<webview> IPC message ${channel} sent by WebContents with <webview> disabled (${event.sender.id})`)
|
||||
throw new Error('<webview> disabled')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleMessage = function (channel, handler) {
|
||||
ipcMainInternal.handle(channel, makeSafeHandler(channel, handler))
|
||||
}
|
||||
|
||||
const handleMessageSync = function (channel, handler) {
|
||||
ipcMainUtils.handleSync(channel, makeSafeHandler(channel, handler))
|
||||
}
|
||||
|
||||
handleMessage('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', function (event, params) {
|
||||
return createGuest(event.sender, params)
|
||||
})
|
||||
|
||||
handleMessageSync('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', function (event, params) {
|
||||
return createGuest(event.sender, params)
|
||||
})
|
||||
|
||||
handleMessage('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', function (event, embedderFrameId, elementInstanceId, guestInstanceId, params) {
|
||||
try {
|
||||
attachGuest(event, embedderFrameId, elementInstanceId, guestInstanceId, params)
|
||||
@@ -346,21 +357,22 @@ ipcMainInternal.on('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', function (event,
|
||||
}
|
||||
})
|
||||
|
||||
const allMethods = new Set([ ...syncMethods, ...asyncMethods ])
|
||||
|
||||
handleMessage('ELECTRON_GUEST_VIEW_MANAGER_CALL', function (event, guestInstanceId, method, args) {
|
||||
const guest = getGuestForWebContents(guestInstanceId, event.sender)
|
||||
if (!allMethods.has(method)) {
|
||||
if (!asyncMethods.has(method)) {
|
||||
throw new Error(`Invalid method: ${method}`)
|
||||
}
|
||||
|
||||
return guest[method](...args)
|
||||
})
|
||||
|
||||
handleMessage('ELECTRON_GUEST_VIEW_MANAGER_CAPTURE_PAGE', async function (event, guestInstanceId, args) {
|
||||
handleMessageSync('ELECTRON_GUEST_VIEW_MANAGER_CALL', function (event, guestInstanceId, method, args) {
|
||||
const guest = getGuestForWebContents(guestInstanceId, event.sender)
|
||||
if (!syncMethods.has(method)) {
|
||||
throw new Error(`Invalid method: ${method}`)
|
||||
}
|
||||
|
||||
return serialize(await guest.capturePage(...args))
|
||||
return guest[method](...args)
|
||||
})
|
||||
|
||||
// Returns WebContents from its guest id hosted in given webContents.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
const electron = require('electron')
|
||||
const { BrowserWindow } = electron
|
||||
const { BrowserWindow, webContents } = require('electron')
|
||||
const { isSameOrigin } = process.electronBinding('v8_util')
|
||||
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal')
|
||||
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils')
|
||||
@@ -75,10 +74,8 @@ const mergeBrowserWindowOptions = function (embedder, options) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!webPreferences.nativeWindowOpen) {
|
||||
// Sets correct openerId here to give correct options to 'new-window' event handler
|
||||
options.webPreferences.openerId = embedder.id
|
||||
}
|
||||
// Sets correct openerId here to give correct options to 'new-window' event handler
|
||||
options.webPreferences.openerId = embedder.id
|
||||
|
||||
return options
|
||||
}
|
||||
@@ -247,11 +244,14 @@ ipcMainInternal.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, url, fra
|
||||
}
|
||||
|
||||
const referrer = { url: '', policy: 'default' }
|
||||
internalWindowOpen(event, url, referrer, frameName, disposition, options, additionalFeatures)
|
||||
ipcMainInternal.emit('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN', event,
|
||||
url, referrer, frameName, disposition, options, additionalFeatures)
|
||||
})
|
||||
|
||||
// Routed window.open messages with fully parsed options
|
||||
function internalWindowOpen (event, url, referrer, frameName, disposition, options, additionalFeatures, postData) {
|
||||
ipcMainInternal.on('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN', function (event, url, referrer,
|
||||
frameName, disposition, options,
|
||||
additionalFeatures, postData) {
|
||||
options = mergeBrowserWindowOptions(event.sender, options)
|
||||
event.sender.emit('new-window', event, url, frameName, disposition, options, additionalFeatures, referrer)
|
||||
const { newGuest } = event
|
||||
@@ -269,22 +269,29 @@ function internalWindowOpen (event, url, referrer, frameName, disposition, optio
|
||||
} else {
|
||||
event.returnValue = createGuest(event.sender, url, referrer, frameName, options, postData)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const handleMessage = function (channel, handler) {
|
||||
ipcMainUtils.handle(channel, (event, guestId, ...args) => {
|
||||
// Access webContents via electron to prevent circular require.
|
||||
const guestContents = electron.webContents.fromId(guestId)
|
||||
const makeSafeHandler = function (handler) {
|
||||
return (event, guestId, ...args) => {
|
||||
const guestContents = webContents.fromId(guestId)
|
||||
if (!guestContents) {
|
||||
throw new Error(`Invalid guestId: ${guestId}`)
|
||||
}
|
||||
|
||||
return handler(event, guestContents, ...args)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const securityCheck = function (contents, guestContents, check) {
|
||||
if (!check(contents, guestContents)) {
|
||||
const handleMessage = function (channel, handler) {
|
||||
ipcMainInternal.handle(channel, makeSafeHandler(handler))
|
||||
}
|
||||
|
||||
const handleMessageSync = function (channel, handler) {
|
||||
ipcMainUtils.handleSync(channel, makeSafeHandler(handler))
|
||||
}
|
||||
|
||||
const assertCanAccessWindow = function (contents, guestContents) {
|
||||
if (!canAccessWindow(contents, guestContents)) {
|
||||
console.error(`Blocked ${contents.getURL()} from accessing guestId: ${guestContents.id}`)
|
||||
throw new Error(`Access denied to guestId: ${guestContents.id}`)
|
||||
}
|
||||
@@ -297,7 +304,7 @@ const windowMethods = new Set([
|
||||
])
|
||||
|
||||
handleMessage('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_METHOD', (event, guestContents, method, ...args) => {
|
||||
securityCheck(event.sender, guestContents, canAccessWindow)
|
||||
assertCanAccessWindow(event.sender, guestContents)
|
||||
|
||||
if (!windowMethods.has(method)) {
|
||||
console.error(`Blocked ${event.sender.getURL()} from calling method: ${method}`)
|
||||
@@ -315,25 +322,22 @@ handleMessage('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestC
|
||||
// The W3C does not seem to have word on how postMessage should work when the
|
||||
// origins do not match, so we do not do |canAccessWindow| check here since
|
||||
// postMessage across origins is useful and not harmful.
|
||||
securityCheck(event.sender, guestContents, isRelatedWindow)
|
||||
|
||||
if (targetOrigin === '*' || isSameOrigin(guestContents.getURL(), targetOrigin)) {
|
||||
const sourceId = event.sender.id
|
||||
guestContents._sendInternal('ELECTRON_GUEST_WINDOW_POSTMESSAGE', sourceId, message, sourceOrigin)
|
||||
}
|
||||
})
|
||||
|
||||
const webContentsMethods = new Set([
|
||||
'getURL',
|
||||
const webContentsMethodsAsync = new Set([
|
||||
'loadURL',
|
||||
'executeJavaScript',
|
||||
'print'
|
||||
])
|
||||
|
||||
handleMessage('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestContents, method, ...args) => {
|
||||
securityCheck(event.sender, guestContents, canAccessWindow)
|
||||
assertCanAccessWindow(event.sender, guestContents)
|
||||
|
||||
if (!webContentsMethods.has(method)) {
|
||||
if (!webContentsMethodsAsync.has(method)) {
|
||||
console.error(`Blocked ${event.sender.getURL()} from calling method: ${method}`)
|
||||
throw new Error(`Invalid method: ${method}`)
|
||||
}
|
||||
@@ -341,4 +345,17 @@ handleMessage('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guest
|
||||
return guestContents[method](...args)
|
||||
})
|
||||
|
||||
exports.internalWindowOpen = internalWindowOpen
|
||||
const webContentsMethodsSync = new Set([
|
||||
'getURL'
|
||||
])
|
||||
|
||||
handleMessageSync('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestContents, method, ...args) => {
|
||||
assertCanAccessWindow(event.sender, guestContents)
|
||||
|
||||
if (!webContentsMethodsSync.has(method)) {
|
||||
console.error(`Blocked ${event.sender.getURL()} from calling method: ${method}`)
|
||||
throw new Error(`Invalid method: ${method}`)
|
||||
}
|
||||
|
||||
return guestContents[method](...args)
|
||||
})
|
||||
|
||||
@@ -151,8 +151,16 @@ app._setDefaultAppPaths(packagePath)
|
||||
// Load the chrome devtools support.
|
||||
require('@electron/internal/browser/devtools')
|
||||
|
||||
const features = process.electronBinding('features')
|
||||
|
||||
// Load the chrome extension support.
|
||||
require('@electron/internal/browser/chrome-extension')
|
||||
if (!features.isExtensionsEnabled()) {
|
||||
require('@electron/internal/browser/chrome-extension')
|
||||
}
|
||||
|
||||
if (features.isRemoteModuleEnabled()) {
|
||||
require('@electron/internal/browser/remote/server')
|
||||
}
|
||||
|
||||
// Load protocol module to ensure it is populated on app ready
|
||||
require('@electron/internal/browser/api/protocol')
|
||||
@@ -187,14 +195,13 @@ app.on('window-all-closed', () => {
|
||||
}
|
||||
})
|
||||
|
||||
const { setDefaultApplicationMenu } = require('@electron/internal/browser/default-menu')
|
||||
|
||||
// Create default menu.
|
||||
//
|
||||
// Note that the task must be added before loading any app, so we can make sure
|
||||
// the call is maded before any user window is created, otherwise the default
|
||||
// menu may show even when user explicitly hides the menu.
|
||||
app.once('ready', setDefaultApplicationMenu)
|
||||
Promise.all([
|
||||
import('@electron/internal/browser/default-menu'),
|
||||
app.whenReady()
|
||||
]).then(([{ setDefaultApplicationMenu }]) => {
|
||||
// Create default menu
|
||||
setDefaultApplicationMenu()
|
||||
})
|
||||
|
||||
if (packagePath) {
|
||||
// Finally load app's main.js and transfer control to C++.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user