Compare commits
284 Commits
v14.0.0-ni
...
v14.0.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e38d14e6ac | ||
|
|
ee491c0719 | ||
|
|
e0c61ed1ae | ||
|
|
5a8a4dd1eb | ||
|
|
407a005ffb | ||
|
|
4d4346ce65 | ||
|
|
b158159351 | ||
|
|
4f75b0423a | ||
|
|
0c72bf0431 | ||
|
|
d8cdc5932f | ||
|
|
60778a7bf5 | ||
|
|
3ae3e53f7d | ||
|
|
3190771c2d | ||
|
|
34f9bdb8d3 | ||
|
|
341dd0518f | ||
|
|
63bac14885 | ||
|
|
9e78d82f4a | ||
|
|
0bd4f67589 | ||
|
|
05d71aead6 | ||
|
|
8ca6d978d3 | ||
|
|
84fd791c04 | ||
|
|
dac75c4094 | ||
|
|
c8cc2d86ad | ||
|
|
ee29959ac4 | ||
|
|
2ae1c823cd | ||
|
|
38ecb5d927 | ||
|
|
bf28ac8990 | ||
|
|
39feb876df | ||
|
|
43a4299bd9 | ||
|
|
de33e61874 | ||
|
|
8ea5dcd44f | ||
|
|
2a5c47fea6 | ||
|
|
9abfbeecf1 | ||
|
|
6699fea2db | ||
|
|
db789bed86 | ||
|
|
ae630f45b8 | ||
|
|
2b1f0ace7a | ||
|
|
2dfcbefcf3 | ||
|
|
fd09f5cd49 | ||
|
|
0f45cd6938 | ||
|
|
678c8382e2 | ||
|
|
aab2479d94 | ||
|
|
6b530bf62d | ||
|
|
a32c39955e | ||
|
|
d27adae569 | ||
|
|
2a3aa7ee0d | ||
|
|
6d89edf590 | ||
|
|
ebd1261e58 | ||
|
|
9957887412 | ||
|
|
a5a8b92894 | ||
|
|
94bce49d0f | ||
|
|
4b59ebefb8 | ||
|
|
5a202219b6 | ||
|
|
f5392751d1 | ||
|
|
8486a73b86 | ||
|
|
23a5789af6 | ||
|
|
9a6ac40593 | ||
|
|
5530497c82 | ||
|
|
5d6b8919b7 | ||
|
|
755af34e1c | ||
|
|
b49248d34c | ||
|
|
272f9db3f8 | ||
|
|
5c3670c68c | ||
|
|
dfe061017f | ||
|
|
d79d073513 | ||
|
|
2dbe781ea3 | ||
|
|
c0d5a148e5 | ||
|
|
fe2f8c31c2 | ||
|
|
3f8f78de50 | ||
|
|
8cd0c8152e | ||
|
|
0fe50bb64e | ||
|
|
e203029c4c | ||
|
|
19cbb030d0 | ||
|
|
12f835858e | ||
|
|
6d39c35de7 | ||
|
|
879b32840b | ||
|
|
5b2a6f6a2b | ||
|
|
0d72f4ee48 | ||
|
|
1666664502 | ||
|
|
4055bf0d58 | ||
|
|
bc0cd83447 | ||
|
|
17c3649811 | ||
|
|
56926d9bee | ||
|
|
2f4e729f8d | ||
|
|
1789cfa5d3 | ||
|
|
5e3bdfd920 | ||
|
|
6128e25ace | ||
|
|
2fcd000f0c | ||
|
|
f1fcdbd4a0 | ||
|
|
014409f98e | ||
|
|
3b39ff300b | ||
|
|
e81d3756d5 | ||
|
|
789bfe627b | ||
|
|
f465439843 | ||
|
|
066e356ada | ||
|
|
7665ba0838 | ||
|
|
b884381311 | ||
|
|
1d0be9d6ed | ||
|
|
f4ed98c43b | ||
|
|
faf3477388 | ||
|
|
8cf7c46570 | ||
|
|
dd5dd2a426 | ||
|
|
0e673d069d | ||
|
|
d24de10707 | ||
|
|
6a429e9d04 | ||
|
|
172ac25013 | ||
|
|
e3a613d103 | ||
|
|
73696eadde | ||
|
|
bdbf78dca8 | ||
|
|
40dbeb6836 | ||
|
|
3ff100521d | ||
|
|
f1752a0b6f | ||
|
|
e67b244571 | ||
|
|
fef79701e0 | ||
|
|
c2877a342c | ||
|
|
4e610b1948 | ||
|
|
4d30e7618a | ||
|
|
7381738d85 | ||
|
|
0f2ad3e384 | ||
|
|
b8812c8942 | ||
|
|
7a11390b8a | ||
|
|
6ab2684234 | ||
|
|
80f051d859 | ||
|
|
95e7c6d53a | ||
|
|
1b4c3428a9 | ||
|
|
8edb7b456f | ||
|
|
6362736703 | ||
|
|
670ae438b9 | ||
|
|
10c6959c7f | ||
|
|
1066dce975 | ||
|
|
d584afdf5b | ||
|
|
0d69ba8ca2 | ||
|
|
c2ba3ab114 | ||
|
|
72a33e79d0 | ||
|
|
3ee0536b1d | ||
|
|
846a12056d | ||
|
|
e0f6313739 | ||
|
|
8866b312ad | ||
|
|
cb8fada7a0 | ||
|
|
b983bda721 | ||
|
|
3125ec093d | ||
|
|
a27329d9ad | ||
|
|
5362882cf6 | ||
|
|
c58446d9d7 | ||
|
|
1c2ed2ba95 | ||
|
|
1c0e496ee2 | ||
|
|
0f32b0f1ce | ||
|
|
d0b9a931cc | ||
|
|
ac079f11f3 | ||
|
|
da35a8af31 | ||
|
|
e3dfe7366a | ||
|
|
e69d0802a7 | ||
|
|
8f2765745c | ||
|
|
8fc86517fa | ||
|
|
12aa6d7343 | ||
|
|
3ffaaf1872 | ||
|
|
e345ef13ca | ||
|
|
32d8809283 | ||
|
|
7209702278 | ||
|
|
77e7d828ee | ||
|
|
241cceb2c9 | ||
|
|
6330f8be9f | ||
|
|
959375affb | ||
|
|
47a6e72114 | ||
|
|
1d77af0aff | ||
|
|
845f756eb6 | ||
|
|
eb4f5e18e6 | ||
|
|
06a8cab4c1 | ||
|
|
d03325541f | ||
|
|
259bf8c4f7 | ||
|
|
4e2934a872 | ||
|
|
039f3d5cd2 | ||
|
|
d79ebc6dc6 | ||
|
|
cd3c6f9e37 | ||
|
|
87dfe1ba99 | ||
|
|
71e232f36d | ||
|
|
77297f37a3 | ||
|
|
014bdc9f8a | ||
|
|
6f9df7983d | ||
|
|
d518b6abc8 | ||
|
|
2806664bd0 | ||
|
|
071fa2ab8f | ||
|
|
5656493676 | ||
|
|
adb85f341b | ||
|
|
af426cbdab | ||
|
|
1bfc16b65a | ||
|
|
99d74799fb | ||
|
|
8cfd249981 | ||
|
|
9b164e5e16 | ||
|
|
dcbabcb23c | ||
|
|
aeb566c38e | ||
|
|
33035f96a2 | ||
|
|
4fe8005f27 | ||
|
|
8f7a385f94 | ||
|
|
04888d2b1f | ||
|
|
1f5d1a4704 | ||
|
|
c68c65f383 | ||
|
|
5e6f8349ec | ||
|
|
1c3339640a | ||
|
|
cba6626af8 | ||
|
|
b7a23450b7 | ||
|
|
4073599f59 | ||
|
|
2eb3bddb05 | ||
|
|
9cf71d72ab | ||
|
|
4b70ccde26 | ||
|
|
e1b58182b9 | ||
|
|
5e1d50d020 | ||
|
|
5233feaef9 | ||
|
|
c0bfef16a0 | ||
|
|
65ff8d940b | ||
|
|
84cc72c415 | ||
|
|
3869bb2b29 | ||
|
|
3ad9c27823 | ||
|
|
c13a523a79 | ||
|
|
5ceec9189e | ||
|
|
432ce94d20 | ||
|
|
48959d72f6 | ||
|
|
abdd349e58 | ||
|
|
ad0d236ea3 | ||
|
|
8944bceae2 | ||
|
|
a51aaeb28f | ||
|
|
e01faedaa5 | ||
|
|
06f51b7283 | ||
|
|
82946133b1 | ||
|
|
35f2ed8978 | ||
|
|
2b84d79b18 | ||
|
|
821c81f5ee | ||
|
|
dca3b41ee6 | ||
|
|
e9b18a8e2a | ||
|
|
33229f6a27 | ||
|
|
5167d11bfc | ||
|
|
3d6adb8c76 | ||
|
|
cb05a1d82f | ||
|
|
f0ad7dd315 | ||
|
|
b1b8db362f | ||
|
|
2173f7b60b | ||
|
|
d3ee141d90 | ||
|
|
aea8d5325c | ||
|
|
1336978de9 | ||
|
|
71e0fb7039 | ||
|
|
9ec43a5092 | ||
|
|
d1219a74cb | ||
|
|
12d76bea53 | ||
|
|
0b816592ee | ||
|
|
3f66dd5765 | ||
|
|
49ef1fe342 | ||
|
|
de55bf8459 | ||
|
|
25f5c01cec | ||
|
|
d5f2eb5a81 | ||
|
|
cbba602eae | ||
|
|
dab9a88413 | ||
|
|
ad4def9af7 | ||
|
|
1fc230158b | ||
|
|
8f8708680f | ||
|
|
a264fc891d | ||
|
|
28143774c1 | ||
|
|
2c65060ec8 | ||
|
|
8d0e7aed9f | ||
|
|
9d9921b533 | ||
|
|
2086e1903c | ||
|
|
476e908269 | ||
|
|
16236a195b | ||
|
|
9b144a6a97 | ||
|
|
e379b455c9 | ||
|
|
71c248176b | ||
|
|
014f2e622e | ||
|
|
9fb3a49c7c | ||
|
|
42e5421276 | ||
|
|
961b74b2ac | ||
|
|
a699dfdf83 | ||
|
|
1dae3da901 | ||
|
|
e5e8ab4eea | ||
|
|
38c877e9d3 | ||
|
|
a0589ca5d7 | ||
|
|
3d6343ed51 | ||
|
|
41bb3f1321 | ||
|
|
005101424a | ||
|
|
99909baeac | ||
|
|
dd80952877 | ||
|
|
0f898b2260 | ||
|
|
b0167b269a | ||
|
|
c17f5a783c | ||
|
|
dc0c52eaa7 | ||
|
|
9601dc59fc |
3
.github/CODEOWNERS
vendored
@@ -12,4 +12,7 @@ DEPS @electron/wg-upgrades
|
||||
/script/release @electron/wg-releases
|
||||
|
||||
# Security WG
|
||||
/lib/browser/devtools.ts @electron/wg-security
|
||||
/lib/browser/guest-view-manager.ts @electron/wg-security
|
||||
/lib/browser/guest-window-proxy.ts @electron/wg-security
|
||||
/lib/browser/rpc-server.ts @electron/wg-security
|
||||
|
||||
57
BUILD.gn
@@ -1,6 +1,7 @@
|
||||
import("//build/config/locales.gni")
|
||||
import("//build/config/ui.gni")
|
||||
import("//build/config/win/manifest.gni")
|
||||
import("//components/os_crypt/features.gni")
|
||||
import("//components/spellcheck/spellcheck_build_features.gni")
|
||||
import("//content/public/app/mac_helpers.gni")
|
||||
import("//extensions/buildflags/buildflags.gni")
|
||||
@@ -25,6 +26,8 @@ import("electron_paks.gni")
|
||||
import("filenames.auto.gni")
|
||||
import("filenames.gni")
|
||||
import("filenames.hunspell.gni")
|
||||
import("filenames.libcxx.gni")
|
||||
import("filenames.libcxxabi.gni")
|
||||
|
||||
if (is_mac) {
|
||||
import("//build/config/mac/rules.gni")
|
||||
@@ -294,7 +297,7 @@ templated_file("electron_version_header") {
|
||||
action("electron_fuses") {
|
||||
script = "build/fuses/build.py"
|
||||
|
||||
inputs = [ "build/fuses/fuses.json" ]
|
||||
inputs = [ "build/fuses/fuses.json5" ]
|
||||
|
||||
outputs = [
|
||||
"$target_gen_dir/fuses.h",
|
||||
@@ -333,8 +336,10 @@ source_set("electron_lib") {
|
||||
"//components/network_hints/common:mojo_bindings",
|
||||
"//components/network_hints/renderer",
|
||||
"//components/network_session_configurator/common",
|
||||
"//components/os_crypt",
|
||||
"//components/pref_registry",
|
||||
"//components/prefs",
|
||||
"//components/security_state/content",
|
||||
"//components/upload_list",
|
||||
"//components/user_prefs",
|
||||
"//components/viz/host",
|
||||
@@ -347,7 +352,6 @@ source_set("electron_lib") {
|
||||
"//device/bluetooth",
|
||||
"//device/bluetooth/public/cpp",
|
||||
"//gin",
|
||||
"//media/blink:blink",
|
||||
"//media/capture/mojom:video_capture",
|
||||
"//media/mojo/mojom",
|
||||
"//net:extras",
|
||||
@@ -364,6 +368,7 @@ source_set("electron_lib") {
|
||||
"//skia",
|
||||
"//third_party/blink/public:blink",
|
||||
"//third_party/blink/public:blink_devtools_inspector_resources",
|
||||
"//third_party/blink/public/platform/media",
|
||||
"//third_party/boringssl",
|
||||
"//third_party/electron_node:node_lib",
|
||||
"//third_party/inspector_protocol:crdtp",
|
||||
@@ -619,6 +624,8 @@ source_set("electron_lib") {
|
||||
sources += [
|
||||
"shell/browser/printing/print_preview_message_handler.cc",
|
||||
"shell/browser/printing/print_preview_message_handler.h",
|
||||
"shell/browser/printing/print_view_manager_electron.cc",
|
||||
"shell/browser/printing/print_view_manager_electron.h",
|
||||
"shell/renderer/printing/print_render_frame_helper_delegate.cc",
|
||||
"shell/renderer/printing/print_render_frame_helper_delegate.h",
|
||||
]
|
||||
@@ -679,6 +686,10 @@ source_set("electron_lib") {
|
||||
]
|
||||
libs += [ "uxtheme.lib" ]
|
||||
}
|
||||
|
||||
if (allow_runtime_configurable_key_storage) {
|
||||
defines += [ "ALLOW_RUNTIME_CONFIGURABLE_KEY_STORAGE" ]
|
||||
}
|
||||
}
|
||||
|
||||
electron_paks("packed_resources") {
|
||||
@@ -1290,13 +1301,18 @@ template("dist_zip") {
|
||||
"testonly",
|
||||
])
|
||||
flatten = false
|
||||
flatten_relative_to = false
|
||||
if (defined(invoker.flatten)) {
|
||||
flatten = invoker.flatten
|
||||
if (defined(invoker.flatten_relative_to)) {
|
||||
flatten_relative_to = invoker.flatten_relative_to
|
||||
}
|
||||
}
|
||||
args = rebase_path(outputs + [ _runtime_deps_file ], root_build_dir) + [
|
||||
target_cpu,
|
||||
target_os,
|
||||
"$flatten",
|
||||
"$flatten_relative_to",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1387,6 +1403,43 @@ dist_zip("hunspell_dictionaries_zip") {
|
||||
outputs = [ "$root_build_dir/hunspell_dictionaries.zip" ]
|
||||
}
|
||||
|
||||
copy("libcxx_headers") {
|
||||
sources = libcxx_headers + libcxx_licenses
|
||||
outputs = [ "$target_gen_dir/electron_libcxx_include/{{source_root_relative_dir}}/{{source_file_part}}" ]
|
||||
}
|
||||
|
||||
dist_zip("libcxx_headers_zip") {
|
||||
data_deps = [ ":libcxx_headers" ]
|
||||
flatten = true
|
||||
flatten_relative_to = rebase_path(
|
||||
"$target_gen_dir/electron_libcxx_include/buildtools/third_party/libc++/trunk",
|
||||
"$root_out_dir")
|
||||
|
||||
outputs = [ "$root_build_dir/libcxx_headers.zip" ]
|
||||
}
|
||||
|
||||
copy("libcxxabi_headers") {
|
||||
sources = libcxxabi_headers + libcxxabi_licenses
|
||||
outputs = [ "$target_gen_dir/electron_libcxxabi_include/{{source_root_relative_dir}}/{{source_file_part}}" ]
|
||||
}
|
||||
|
||||
dist_zip("libcxxabi_headers_zip") {
|
||||
data_deps = [ ":libcxxabi_headers" ]
|
||||
flatten = true
|
||||
flatten_relative_to = rebase_path(
|
||||
"$target_gen_dir/electron_libcxxabi_include/buildtools/third_party/libc++abi/trunk",
|
||||
"$root_out_dir")
|
||||
|
||||
outputs = [ "$root_build_dir/libcxxabi_headers.zip" ]
|
||||
}
|
||||
|
||||
action("libcxx_objects_zip") {
|
||||
deps = [ "//buildtools/third_party/libc++" ]
|
||||
script = "build/zip_libcxx.py"
|
||||
outputs = [ "$root_build_dir/libcxx_objects.zip" ]
|
||||
args = rebase_path(outputs)
|
||||
}
|
||||
|
||||
group("electron") {
|
||||
public_deps = [ ":electron_app" ]
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ Issues are created [here](https://github.com/electron/electron/issues/new).
|
||||
|
||||
### Issue Closure
|
||||
|
||||
Bug reports will be closed if the issue has been inactive and the latest affected version no longer receives support. At the moment, Electron maintains its three latest major versions, with a new major version being released every 12 weeks. (For more information on Electron's release cadence, see [this blog post](https://electronjs.org/blog/12-week-cadence).)
|
||||
Bug reports will be closed if the issue has been inactive and the latest affected version no longer receives support. At the moment, Electron maintains its three latest major versions, with a new major version being released every 8 weeks. (For more information on Electron's release cadence, see [this blog post](https://electronjs.org/blog/8-week-cadence).)
|
||||
|
||||
_If an issue has been closed and you still feel it's relevant, feel free to ping a maintainer or add a comment!_
|
||||
|
||||
|
||||
14
DEPS
@@ -10,17 +10,21 @@ gclient_gn_args = [
|
||||
'checkout_openxr',
|
||||
'checkout_google_benchmark',
|
||||
'mac_xcode_version',
|
||||
'generate_location_tags',
|
||||
]
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'92.0.4488.0',
|
||||
'93.0.4566.0',
|
||||
'node_version':
|
||||
'v14.16.1',
|
||||
'v14.17.0',
|
||||
'nan_version':
|
||||
'v2.14.2',
|
||||
# The following commit hash of NAN is v2.14.2 with *only* changes to the
|
||||
# test suite. This should be updated to a specific tag when one becomes
|
||||
# available.
|
||||
'65b32af46e9d7fab2e4ff657751205b3865f4920',
|
||||
'squirrel.mac_version':
|
||||
'cdc0729c8bf8576bfef18629186e1e9ecf1b0d9f',
|
||||
'0e5d146ba13101a1302d59ea6e6e0b3cace4ae38',
|
||||
|
||||
'pyyaml_version': '3.12',
|
||||
|
||||
@@ -52,6 +56,8 @@ vars = {
|
||||
|
||||
'mac_xcode_version': 'default',
|
||||
|
||||
'generate_location_tags': False,
|
||||
|
||||
# To allow running hooks without parsing the DEPS tree
|
||||
'process_deps': True,
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
14.0.0-nightly.20210430
|
||||
14.0.0-beta.17
|
||||
@@ -5,7 +5,7 @@
|
||||
[](https://david-dm.org/electron/electron?type=dev)
|
||||
[](https://discord.com/invite/electron)
|
||||
|
||||
:memo: Available Translations: 🇨🇳 🇹🇼 🇧🇷 🇪🇸 🇰🇷 🇯🇵 🇷🇺 🇫🇷 🇹🇭 🇳🇱 🇹🇷 🇮🇩 🇺🇦 🇨🇿 🇮🇹 🇵🇱.
|
||||
:memo: Available Translations: 🇨🇳 🇧🇷 🇪🇸 🇯🇵 🇷🇺 🇫🇷 🇺🇸 🇩🇪.
|
||||
View these docs in other languages at [electron/i18n](https://github.com/electron/i18n/tree/master/content/).
|
||||
|
||||
The Electron framework lets you write cross-platform desktop applications
|
||||
|
||||
@@ -229,7 +229,5 @@ deploy_script:
|
||||
& python script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
} elseif (Test-Path Env:\TEST_WOA) {
|
||||
# temporarily disabled due to issues from chromium roll
|
||||
# node script/release/ci-release-build.js --job=electron-woa-testing --ci=VSTS --armTest --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH
|
||||
echo "Skipping WOA testing for now"
|
||||
node script/release/ci-release-build.js --job=electron-woa-testing --ci=VSTS --armTest --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH
|
||||
}
|
||||
|
||||
@@ -28,3 +28,8 @@ libcxx_abi_unstable = false
|
||||
enable_pseudolocales = false
|
||||
|
||||
is_cfi = false
|
||||
|
||||
# Make application name configurable at runtime for cookie crypto
|
||||
allow_runtime_configurable_key_storage = true
|
||||
|
||||
enable_cet_shadow_stack = false
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from collections import OrderedDict
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
@@ -49,8 +50,8 @@ const volatile char kFuseWire[] = { /* sentinel */ {sentinel}, /* fuse_version *
|
||||
}
|
||||
"""
|
||||
|
||||
with open(os.path.join(dir_path, "fuses.json"), 'r') as f:
|
||||
fuse_defaults = json.load(f)
|
||||
with open(os.path.join(dir_path, "fuses.json5"), 'r') as f:
|
||||
fuse_defaults = json.loads(''.join(line for line in f.readlines() if not line.strip()[0] == "/"), object_pairs_hook=OrderedDict)
|
||||
|
||||
fuse_version = fuse_defaults['_version']
|
||||
del fuse_defaults['_version']
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
"_comment": "Modifying the fuse schema in any breaking way should result in the _version prop being incremented. NEVER remove a fuse or change its meaning, instead mark it as removed with 'r'",
|
||||
"_schema": "0 == off, 1 == on, r == removed fuse",
|
||||
"_version": 1,
|
||||
"run_as_node": "1"
|
||||
"run_as_node": "1",
|
||||
"cookie_encryption": "0"
|
||||
}
|
||||
@@ -16,5 +16,5 @@ try:
|
||||
subprocess.check_output(args, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
error_msg = "NPM script '{}' failed with code '{}':\n".format(sys.argv[2], e.returncode)
|
||||
print(error_msg + e.output.decode('ascii'))
|
||||
print(error_msg + e.output.decode('utf8'))
|
||||
sys.exit(e.returncode)
|
||||
|
||||
18
build/zip.py
@@ -39,7 +39,8 @@ PATHS_TO_SKIP = [
|
||||
'./crashpad_handler',
|
||||
# Skip because these are outputs that we don't need.
|
||||
'resources/inspector',
|
||||
'gen/third_party/devtools-frontend/src'
|
||||
'gen/third_party/devtools-frontend/src',
|
||||
'gen/ui/webui'
|
||||
]
|
||||
|
||||
def skip_path(dep, dist_zip, target_cpu):
|
||||
@@ -71,7 +72,7 @@ def execute(argv):
|
||||
raise e
|
||||
|
||||
def main(argv):
|
||||
dist_zip, runtime_deps, target_cpu, _, flatten_val = argv
|
||||
dist_zip, runtime_deps, target_cpu, _, flatten_val, flatten_relative_to = argv
|
||||
should_flatten = flatten_val == "true"
|
||||
dist_files = set()
|
||||
with open(runtime_deps) as f:
|
||||
@@ -98,11 +99,18 @@ def main(argv):
|
||||
if basename == 'chrome_sandbox'
|
||||
else dep
|
||||
)
|
||||
name_to_write = arcname
|
||||
if should_flatten:
|
||||
if flatten_relative_to:
|
||||
if name_to_write.startswith(flatten_relative_to):
|
||||
name_to_write = name_to_write[len(flatten_relative_to):]
|
||||
else:
|
||||
name_to_write = os.path.basename(arcname)
|
||||
else:
|
||||
name_to_write = os.path.basename(arcname)
|
||||
z.write(
|
||||
dep,
|
||||
os.path.basename(arcname)
|
||||
if should_flatten
|
||||
else arcname,
|
||||
name_to_write,
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
47
build/zip_libcxx.py
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
def execute(argv):
|
||||
try:
|
||||
output = subprocess.check_output(argv, stderr=subprocess.STDOUT)
|
||||
return output
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(e.output)
|
||||
raise e
|
||||
|
||||
def get_object_files(base_path, archive_name):
|
||||
archive_file = os.path.join(base_path, archive_name)
|
||||
output = execute(['nm', '-g', archive_file]).decode('ascii')
|
||||
object_files = set()
|
||||
lines = output.split("\n")
|
||||
for line in lines:
|
||||
if line.startswith(base_path):
|
||||
object_file = line.split(":")[0]
|
||||
object_files.add(object_file)
|
||||
if line.startswith('nm: '):
|
||||
object_file = line.split(":")[1].lstrip()
|
||||
object_files.add(object_file)
|
||||
return list(object_files) + [archive_file]
|
||||
|
||||
def main(argv):
|
||||
dist_zip, = argv
|
||||
out_dir = os.path.dirname(dist_zip)
|
||||
base_path_libcxx = os.path.join(out_dir, 'obj/buildtools/third_party/libc++')
|
||||
base_path_libcxxabi = os.path.join(out_dir, 'obj/buildtools/third_party/libc++abi')
|
||||
object_files_libcxx = get_object_files(base_path_libcxx, 'libc++.a')
|
||||
object_files_libcxxabi = get_object_files(base_path_libcxxabi, 'libc++abi.a')
|
||||
with zipfile.ZipFile(
|
||||
dist_zip, 'w', zipfile.ZIP_DEFLATED, allowZip64=True
|
||||
) as z:
|
||||
object_files_libcxx.sort()
|
||||
for object_file in object_files_libcxx:
|
||||
z.write(object_file, os.path.relpath(object_file, base_path_libcxx))
|
||||
for object_file in object_files_libcxxabi:
|
||||
z.write(object_file, os.path.relpath(object_file, base_path_libcxxabi))
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
@@ -43,8 +43,6 @@ 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/ssl/security_state_tab_helper.cc",
|
||||
"//chrome/browser/ssl/security_state_tab_helper.h",
|
||||
"//chrome/browser/ui/views/autofill/autofill_popup_view_utils.cc",
|
||||
"//chrome/browser/ui/views/autofill/autofill_popup_view_utils.h",
|
||||
"//extensions/browser/app_window/size_constraints.cc",
|
||||
@@ -80,7 +78,6 @@ static_library("chrome") {
|
||||
"//components/keyed_service/content",
|
||||
"//components/paint_preview/buildflags",
|
||||
"//components/proxy_config",
|
||||
"//components/security_state/content",
|
||||
"//content/public/browser",
|
||||
"//services/strings",
|
||||
]
|
||||
@@ -91,6 +88,10 @@ static_library("chrome") {
|
||||
"//components/optimization_guide/proto:optimization_guide_proto",
|
||||
]
|
||||
|
||||
if (enable_basic_printing && is_win) {
|
||||
deps += [ "//chrome/common:cloud_print_utility_mojom" ]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
sources += [ "//chrome/browser/icon_loader_auralinux.cc" ]
|
||||
if (use_x11 || use_ozone) {
|
||||
@@ -145,6 +146,8 @@ static_library("chrome") {
|
||||
|
||||
if (enable_color_chooser) {
|
||||
sources += [
|
||||
"//chrome/browser/devtools/devtools_eye_dropper.cc",
|
||||
"//chrome/browser/devtools/devtools_eye_dropper.h",
|
||||
"//chrome/browser/platform_util.cc",
|
||||
"//chrome/browser/platform_util.h",
|
||||
"//chrome/browser/ui/browser_dialogs.h",
|
||||
@@ -219,8 +222,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/printing/print_job_worker.h",
|
||||
"//chrome/browser/printing/print_view_manager_base.cc",
|
||||
"//chrome/browser/printing/print_view_manager_base.h",
|
||||
"//chrome/browser/printing/print_view_manager_basic.cc",
|
||||
"//chrome/browser/printing/print_view_manager_basic.h",
|
||||
"//chrome/browser/printing/printer_query.cc",
|
||||
"//chrome/browser/printing/printer_query.h",
|
||||
"//chrome/browser/printing/printing_service.cc",
|
||||
|
||||
@@ -157,15 +157,14 @@ void CertificateManagerModel::GetCertDBOnIOThread(
|
||||
CreationCallback callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
auto did_get_cert_db_callback = base::AdaptCallbackForRepeating(
|
||||
base::BindOnce(&CertificateManagerModel::DidGetCertDBOnIOThread,
|
||||
std::move(callback)));
|
||||
auto split_callback = base::SplitOnceCallback(base::BindOnce(
|
||||
&CertificateManagerModel::DidGetCertDBOnIOThread, std::move(callback)));
|
||||
|
||||
net::NSSCertDatabase* cert_db =
|
||||
GetNSSCertDatabaseForResourceContext(context, did_get_cert_db_callback);
|
||||
net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext(
|
||||
context, std::move(split_callback.first));
|
||||
|
||||
// If the NSS database was already available, |cert_db| is non-null and
|
||||
// |did_get_cert_db_callback| has not been called. Call it explicitly.
|
||||
if (cert_db)
|
||||
did_get_cert_db_callback.Run(cert_db);
|
||||
std::move(split_callback.second).Run(cert_db);
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ class ProcessSingleton {
|
||||
|
||||
// Function to call when the other process is hung and needs to be killed.
|
||||
// Allows overriding for tests.
|
||||
base::Callback<void(int)> kill_callback_;
|
||||
base::RepeatingCallback<void(int)> kill_callback_;
|
||||
|
||||
// Path in file system to the socket.
|
||||
base::FilePath socket_path_;
|
||||
|
||||
@@ -109,7 +109,7 @@ function loadApplicationPackage (packagePath: string) {
|
||||
|
||||
try {
|
||||
const filePath = Module._resolveFilename(packagePath, module, true);
|
||||
app._setDefaultAppPaths(appPath || path.dirname(filePath));
|
||||
app.setAppPath(appPath || path.dirname(filePath));
|
||||
} catch (e) {
|
||||
showErrorMessage(`Unable to find Electron app at ${packagePath}\n\n${e.message}`);
|
||||
return;
|
||||
|
||||
@@ -18,20 +18,14 @@ an issue:
|
||||
|
||||
## Guides and Tutorials
|
||||
|
||||
### Quickstart
|
||||
### Getting started
|
||||
|
||||
* [Quick Start Guide](tutorial/quick-start.md)
|
||||
* [Prerequisites](tutorial/quick-start.md#prerequisites)
|
||||
* [Create a basic application](tutorial/quick-start.md#create-a-basic-application)
|
||||
* [Run your application](tutorial/quick-start.md#run-your-application)
|
||||
* [Package and distribute the application](tutorial/quick-start.md#package-and-distribute-the-application)
|
||||
* [Introduction](tutorial/introduction.md)
|
||||
* [Quick Start](tutorial/quick-start.md)
|
||||
* [Process Model](tutorial/process-model.md)
|
||||
|
||||
### Learning the basics
|
||||
|
||||
* [Electron's Process Model](tutorial/quick-start.md#application-architecture)
|
||||
* [Main and Renderer Processes](tutorial/quick-start.md#main-and-renderer-processes)
|
||||
* [Electron API](tutorial/quick-start.md#electron-api)
|
||||
* [Node.js API](tutorial/quick-start.md#nodejs-api)
|
||||
* Adding Features to Your App
|
||||
* [Notifications](tutorial/notifications.md)
|
||||
* [Recent Documents](tutorial/recent-documents.md)
|
||||
@@ -59,6 +53,7 @@ an issue:
|
||||
* [Using Native Node.js Modules](tutorial/using-native-node-modules.md)
|
||||
* [Performance Strategies](tutorial/performance.md)
|
||||
* [Security Strategies](tutorial/security.md)
|
||||
* [Process Sandboxing](tutorial/sandbox.md)
|
||||
* [Accessibility](tutorial/accessibility.md)
|
||||
* [Manually Enabling Accessibility Features](tutorial/accessibility.md#manually-enabling-accessibility-features)
|
||||
* [Testing and Debugging](tutorial/application-debugging.md)
|
||||
@@ -68,6 +63,7 @@ an issue:
|
||||
* [Testing on Headless CI Systems (Travis, Jenkins)](tutorial/testing-on-headless-ci.md)
|
||||
* [DevTools Extension](tutorial/devtools-extension.md)
|
||||
* [Automated Testing with a Custom Driver](tutorial/automated-testing-with-a-custom-driver.md)
|
||||
* [REPL](tutorial/repl.md)
|
||||
* [Distribution](tutorial/application-distribution.md)
|
||||
* [Supported Platforms](tutorial/support.md#supported-platforms)
|
||||
* [Code Signing](tutorial/code-signing.md)
|
||||
|
||||
@@ -35,7 +35,7 @@ Linux and Windows to define some accelerators.
|
||||
Use `Alt` instead of `Option`. The `Option` key only exists on macOS, whereas
|
||||
the `Alt` key is available on all platforms.
|
||||
|
||||
The `Super` key is mapped to the `Windows` key on Windows and Linux and
|
||||
The `Super` (or `Meta`) key is mapped to the `Windows` key on Windows and Linux and
|
||||
`Cmd` on macOS.
|
||||
|
||||
## Available modifiers
|
||||
@@ -48,6 +48,7 @@ The `Super` key is mapped to the `Windows` key on Windows and Linux and
|
||||
* `AltGr`
|
||||
* `Shift`
|
||||
* `Super`
|
||||
* `Meta`
|
||||
|
||||
## Available key codes
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL('https://github.com')
|
||||
|
||||
// Or load a local HTML file
|
||||
win.loadURL(`file://${__dirname}/app/index.html`)
|
||||
win.loadFile('index.html')
|
||||
```
|
||||
|
||||
## Frameless window
|
||||
@@ -238,7 +238,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
window shadow and window animations. Default is `true`.
|
||||
* `vibrancy` String (optional) - Add a type of vibrancy effect to the window, only on
|
||||
macOS. Can be `appearance-based`, `light`, `dark`, `titlebar`, `selection`,
|
||||
`menu`, `popover`, `sidebar`, `medium-light`, `ultra-dark`, `header`, `sheet`, `window`, `hud`, `fullscreen-ui`, `tooltip`, `content`, `under-window`, or `under-page`. Please note that using `frame: false` in combination with a vibrancy value requires that you use a non-default `titleBarStyle` as well. Also note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` are deprecated and have been removed in macOS Catalina (10.15).
|
||||
`menu`, `popover`, `sidebar`, `medium-light`, `ultra-dark`, `header`, `sheet`, `window`, `hud`, `fullscreen-ui`, `tooltip`, `content`, `under-window`, or `under-page`. Please note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` are deprecated and have been removed in macOS Catalina (10.15).
|
||||
* `zoomToPageWidth` Boolean (optional) - Controls the behavior on macOS when
|
||||
option-clicking the green stoplight button on the toolbar or by clicking the
|
||||
Window > Zoom menu item. If `true`, the window will grow to the preferred
|
||||
@@ -272,7 +272,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
associated with the window, making it compatible with the Chromium
|
||||
OS-level sandbox and disabling the Node.js engine. This is not the same as
|
||||
the `nodeIntegration` option and the APIs available to the preload script
|
||||
are more limited. Read more about the option [here](sandbox-option.md).
|
||||
are more limited. Read more about the option [here](../tutorial/sandbox.md).
|
||||
* `session` [Session](session.md#class-session) (optional) - Sets the session used by the
|
||||
page. Instead of passing the Session object directly, you can also choose to
|
||||
use the `partition` option instead, which accepts a partition string. When
|
||||
@@ -342,8 +342,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
context in the dev tools by selecting the 'Electron Isolated Context'
|
||||
entry in the combo box at the top of the Console tab.
|
||||
* `nativeWindowOpen` Boolean (optional) - Whether to use native
|
||||
`window.open()`. Defaults to `true`. Child windows will always have node
|
||||
integration disabled unless `nodeIntegrationInSubFrames` is true.
|
||||
`window.open()`. Defaults to `false`. Child windows will always have node
|
||||
integration disabled unless `nodeIntegrationInSubFrames` is true. **Note:** The default
|
||||
value will be changing to `true` in Electron 15.
|
||||
* `webviewTag` Boolean (optional) - Whether to enable the [`<webview>` tag](webview-tag.md).
|
||||
Defaults to `false`. **Note:** The
|
||||
`preload` script configured for the `<webview>` will have node integration
|
||||
@@ -391,6 +392,10 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
contain the layout of the document—without requiring scrolling. Enabling
|
||||
this will cause the `preferred-size-changed` event to be emitted on the
|
||||
`WebContents` when the preferred size changes. Default is `false`.
|
||||
* `titleBarOverlay` Boolean (optional) - On macOS, when using a frameless window in conjunction with
|
||||
`win.setWindowButtonVisibility(true)` or using a `titleBarStyle` so that the traffic lights are visible,
|
||||
this property enables the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and
|
||||
[CSS Environment Variables][overlay-css-env-vars]. Default is `false`.
|
||||
|
||||
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
|
||||
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
|
||||
@@ -1805,3 +1810,5 @@ removed in future Electron releases.
|
||||
[window-levels]: https://developer.apple.com/documentation/appkit/nswindow/level
|
||||
[chrome-content-scripts]: https://developer.chrome.com/extensions/content_scripts#execution-environment
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[overlay-javascript-apis]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#javascript-apis
|
||||
[overlay-css-env-vars]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#css-environment-variables
|
||||
|
||||
@@ -71,7 +71,7 @@ const request = net.request({
|
||||
|
||||
Returns:
|
||||
|
||||
* `response` IncomingMessage - An object representing the HTTP response message.
|
||||
* `response` [IncomingMessage](incoming-message.md) - An object representing the HTTP response message.
|
||||
|
||||
#### Event: 'login'
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ const { clipboard } = require('electron')
|
||||
|
||||
const hasFormat = clipboard.has('<p>selection</p>')
|
||||
console.log(hasFormat)
|
||||
// 'true' or 'false
|
||||
// 'true' or 'false'
|
||||
```
|
||||
|
||||
### `clipboard.read(format)` _Experimental_
|
||||
@@ -208,6 +208,10 @@ console.log(hasFormat)
|
||||
|
||||
Returns `String` - Reads `format` type from the clipboard.
|
||||
|
||||
`format` should contain valid ASCII characters and have `/` separator.
|
||||
`a/c`, `a/bc` are valid formats while `/abc`, `abc/`, `a/`, `/a`, `a`
|
||||
are not valid.
|
||||
|
||||
### `clipboard.readBuffer(format)` _Experimental_
|
||||
|
||||
* `format` String
|
||||
@@ -218,9 +222,9 @@ Returns `Buffer` - Reads `format` type from the clipboard.
|
||||
const { clipboard } = require('electron')
|
||||
|
||||
const buffer = Buffer.from('this is binary', 'utf8')
|
||||
clipboard.writeBuffer('public.utf8-plain-text', buffer)
|
||||
clipboard.writeBuffer('public/utf8-plain-text', buffer)
|
||||
|
||||
const ret = clipboard.readBuffer('public.utf8-plain-text')
|
||||
const ret = clipboard.readBuffer('public/utf8-plain-text')
|
||||
|
||||
console.log(buffer.equals(out))
|
||||
// true
|
||||
@@ -238,7 +242,7 @@ Writes the `buffer` into the clipboard as `format`.
|
||||
const { clipboard } = require('electron')
|
||||
|
||||
const buffer = Buffer.from('writeBuffer', 'utf8')
|
||||
clipboard.writeBuffer('public.utf8-plain-text', buffer)
|
||||
clipboard.writeBuffer('public/utf8-plain-text', buffer)
|
||||
```
|
||||
|
||||
### `clipboard.write(data[, type])`
|
||||
|
||||
@@ -67,15 +67,24 @@ Enables caller stack logging for the following APIs (filtering events):
|
||||
|
||||
* `desktopCapturer.getSources()` / `desktop-capturer-get-sources`
|
||||
|
||||
### --enable-logging
|
||||
### --enable-logging[=file]
|
||||
|
||||
Prints Chromium's logging into console.
|
||||
Prints Chromium's logging to stderr (or a log file).
|
||||
|
||||
This switch can not be used in `app.commandLine.appendSwitch` since it is parsed
|
||||
earlier than user's app is loaded, but you can set the `ELECTRON_ENABLE_LOGGING`
|
||||
environment variable to achieve the same effect.
|
||||
The `ELECTRON_ENABLE_LOGGING` environment variable has the same effect as
|
||||
passing `--enable-logging`.
|
||||
|
||||
## --force-fieldtrials=`trials`
|
||||
Passing `--enable-logging` will result in logs being printed on stderr.
|
||||
Passing `--enable-logging=file` will result in logs being saved to the file
|
||||
specified by `--log-file=...`, or to `electron_debug.log` in the user-data
|
||||
directory if `--log-file` is not specified.
|
||||
|
||||
> **Note:** On Windows, logs from child processes cannot be sent to stderr.
|
||||
> Logging to a file is the most reliable way to collect logs on Windows.
|
||||
|
||||
See also `--log-file`, `--log-level`, `--v`, and `--vmodule`.
|
||||
|
||||
### --force-fieldtrials=`trials`
|
||||
|
||||
Field trials to be forcefully enabled or disabled.
|
||||
|
||||
@@ -126,10 +135,37 @@ See the [Node.js documentation][node-cli] or run `node --help` in your terminal
|
||||
|
||||
Set a custom locale.
|
||||
|
||||
### --log-file=`path`
|
||||
|
||||
If `--enable-logging` is specified, logs will be written to the given path. The
|
||||
parent directory must exist.
|
||||
|
||||
Setting the `ELECTRON_LOG_FILE` environment variable is equivalent to passing
|
||||
this flag. If both are present, the command-line switch takes precedence.
|
||||
|
||||
### --log-net-log=`path`
|
||||
|
||||
Enables net log events to be saved and writes them to `path`.
|
||||
|
||||
### --log-level=`N`
|
||||
|
||||
Sets the verbosity of logging when used together with `--enable-logging`.
|
||||
`N` should be one of [Chrome's LogSeverities][severities].
|
||||
|
||||
Note that two complimentary logging mechanisms in Chromium -- `LOG()`
|
||||
and `VLOG()` -- are controlled by different switches. `--log-level`
|
||||
controls `LOG()` messages, while `--v` and `--vmodule` control `VLOG()`
|
||||
messages. So you may want to use a combination of these three switches
|
||||
depending on the granularity you want and what logging calls are made
|
||||
by the code you're trying to watch.
|
||||
|
||||
See [Chromium Logging source][logging] for more information on how
|
||||
`LOG()` and `VLOG()` interact. Loosely speaking, `VLOG()` can be thought
|
||||
of as sub-levels / per-module levels inside `LOG(INFO)` to control the
|
||||
firehose of `LOG(INFO)` data.
|
||||
|
||||
See also `--enable-logging`, `--log-level`, `--v`, and `--vmodule`.
|
||||
|
||||
### --no-proxy-server
|
||||
|
||||
Don't use a proxy server and always make direct connections. Overrides any other
|
||||
@@ -137,7 +173,8 @@ proxy server flags that are passed.
|
||||
|
||||
### --no-sandbox
|
||||
|
||||
Disables Chromium sandbox, which is now enabled by default.
|
||||
Disables the Chromium [sandbox](https://www.chromium.org/developers/design-documents/sandbox).
|
||||
Forces renderer process and Chromium helper processes to run un-sandboxed.
|
||||
Should only be used for testing.
|
||||
|
||||
### --proxy-bypass-list=`hosts`
|
||||
@@ -180,6 +217,8 @@ positive values are used for V-logging levels.
|
||||
|
||||
This switch only works when `--enable-logging` is also passed.
|
||||
|
||||
See also `--enable-logging`, `--log-level`, and `--vmodule`.
|
||||
|
||||
### --vmodule=`pattern`
|
||||
|
||||
Gives the per-module maximal V-logging levels to override the value given by
|
||||
@@ -192,6 +231,8 @@ logging level for all code in the source files under a `foo/bar` directory.
|
||||
|
||||
This switch only works when `--enable-logging` is also passed.
|
||||
|
||||
See also `--enable-logging`, `--log-level`, and `--v`.
|
||||
|
||||
### --force_high_performance_gpu
|
||||
|
||||
Force using discrete GPU when there are multiple GPUs available.
|
||||
@@ -239,4 +280,8 @@ By default inspector websocket url is available in stderr and under /json/list e
|
||||
[ready]: app.md#event-ready
|
||||
[play-silent-audio]: https://github.com/atom/atom/pull/9485/files
|
||||
[debugging-main-process]: ../tutorial/debugging-main-process.md
|
||||
[logging]: https://source.chromium.org/chromium/chromium/src/+/master:base/logging.h
|
||||
[node-cli]: https://nodejs.org/api/cli.html
|
||||
[play-silent-audio]: https://github.com/atom/atom/pull/9485/files
|
||||
[ready]: app.md#event-ready
|
||||
[severities]: https://source.chromium.org/chromium/chromium/src/+/master:base/logging.h?q=logging::LogSeverity&ss=chromium
|
||||
|
||||
@@ -41,7 +41,7 @@ When `contextIsolation` is enabled in your `webPreferences` (this is the default
|
||||
|
||||
The `contextBridge` module has the following methods:
|
||||
|
||||
### `contextBridge.exposeInMainWorld(apiKey, api)` _Experimental_
|
||||
### `contextBridge.exposeInMainWorld(apiKey, api)`
|
||||
|
||||
* `apiKey` String - The key to inject the API onto `window` with. The API will be accessible on `window[apiKey]`.
|
||||
* `api` any - Your API, more information on what this API can be and how it works is available below.
|
||||
@@ -50,7 +50,7 @@ The `contextBridge` module has the following methods:
|
||||
|
||||
### API
|
||||
|
||||
The `api` provided to [`exposeInMainWorld`](#contextbridgeexposeinmainworldapikey-api-experimental) must be a `Function`, `String`, `Number`, `Array`, `Boolean`, or an object
|
||||
The `api` provided to [`exposeInMainWorld`](#contextbridgeexposeinmainworldapikey-api) must be a `Function`, `String`, `Number`, `Array`, `Boolean`, or 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**. Any data / primitives sent in
|
||||
|
||||
@@ -24,7 +24,7 @@ The `dialog` module has the following methods:
|
||||
* `buttonLabel` String (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
use. The following values are supported:
|
||||
* `openFile` - Allow files to be selected.
|
||||
* `openDirectory` - Allow directories to be selected.
|
||||
@@ -87,7 +87,7 @@ dialog.showOpenDialogSync(mainWindow, {
|
||||
* `buttonLabel` String (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
use. The following values are supported:
|
||||
* `openFile` - Allow files to be selected.
|
||||
* `openDirectory` - Allow directories to be selected.
|
||||
@@ -112,7 +112,7 @@ Returns `Promise<Object>` - Resolve with an object containing the following:
|
||||
|
||||
* `canceled` Boolean - whether or not the dialog was canceled.
|
||||
* `filePaths` String[] - An array of file paths chosen by the user. If the dialog is cancelled this will be an empty array.
|
||||
* `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the `filePaths` array of base64 encoded strings which contains security scoped bookmark data. `securityScopedBookmarks` must be enabled for this to be populated. (For return values, see [table here](#bookmarks-array).)
|
||||
* `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the `filePaths` array of base64 encoded strings which contains security scoped bookmark data. `securityScopedBookmarks` must be enabled for this to be populated. (For return values, see [table here](#bookmarks-array).)
|
||||
|
||||
The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.
|
||||
|
||||
@@ -154,7 +154,7 @@ dialog.showOpenDialog(mainWindow, {
|
||||
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) (optional)
|
||||
* `options` Object
|
||||
* `title` String (optional)
|
||||
* `title` String (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
|
||||
* `defaultPath` String (optional) - Absolute directory path, absolute file
|
||||
path, or file name to use by default.
|
||||
* `buttonLabel` String (optional) - Custom label for the confirmation button, when
|
||||
@@ -165,7 +165,7 @@ 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)
|
||||
* `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,
|
||||
@@ -185,7 +185,7 @@ The `filters` specifies an array of file types that can be displayed, see
|
||||
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) (optional)
|
||||
* `options` Object
|
||||
* `title` String (optional)
|
||||
* `title` String (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
|
||||
* `defaultPath` String (optional) - Absolute directory path, absolute file
|
||||
path, or file name to use by default.
|
||||
* `buttonLabel` String (optional) - Custom label for the confirmation button, when
|
||||
@@ -195,7 +195,7 @@ The `filters` specifies an array of file types that can be displayed, see
|
||||
* `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`.
|
||||
* `properties` String[] (optional)
|
||||
* `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,
|
||||
@@ -227,7 +227,7 @@ expanding and collapsing the dialog.
|
||||
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
|
||||
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
|
||||
`"error"` display the same warning icon.
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
will result in one button labeled "OK".
|
||||
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
|
||||
be selected by default when the message box opens.
|
||||
@@ -269,7 +269,7 @@ If `browserWindow` is not shown dialog will not be attached to it. In such case
|
||||
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
|
||||
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
|
||||
`"error"` display the same warning icon.
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
will result in one button labeled "OK".
|
||||
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
|
||||
be selected by default when the message box opens.
|
||||
|
||||
@@ -118,7 +118,19 @@ debugging purposes.
|
||||
|
||||
### `ELECTRON_ENABLE_LOGGING`
|
||||
|
||||
Prints Chrome's internal logging to the console.
|
||||
Prints Chromium's internal logging to the console.
|
||||
|
||||
Setting this variable is the same as passing `--enable-logging`
|
||||
on the command line. For more info, see `--enable-logging` in [command-line
|
||||
switches](./command-line-switches.md#enable-loggingfile).
|
||||
|
||||
### `ELECTRON_LOG_FILE`
|
||||
|
||||
Sets the file destination for Chromium's internal logging.
|
||||
|
||||
Setting this variable is the same as passing `--log-file`
|
||||
on the command line. For more info, see `--log-file` in [command-line
|
||||
switches](./command-line-switches.md#log-filepath).
|
||||
|
||||
### `ELECTRON_DEBUG_DRAG_REGIONS`
|
||||
|
||||
@@ -127,7 +139,8 @@ green and non-draggable regions will be colored red to aid debugging.
|
||||
|
||||
### `ELECTRON_DEBUG_NOTIFICATIONS`
|
||||
|
||||
Adds extra logs to [`Notification`](./notification.md) lifecycles on macOS to aid in debugging. Extra logging will be displayed when new Notifications are created or activated. They will also be displayed when common actions are taken: a notification is shown, dismissed, its button is clicked, or it is replied to.
|
||||
Adds extra logs to [`Notification`](./notification.md) lifecycles on macOS to aid in debugging. Extra logging will be displayed when new Notifications are created or activated. They will also be displayed when common a
|
||||
tions are taken: a notification is shown, dismissed, its button is clicked, or it is replied to.
|
||||
|
||||
Sample output:
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ The following methods of `chrome.runtime` are supported:
|
||||
- `chrome.runtime.getURL`
|
||||
- `chrome.runtime.connect`
|
||||
- `chrome.runtime.sendMessage`
|
||||
- `chrome.runtime.reload`
|
||||
|
||||
The following events of `chrome.runtime` are supported:
|
||||
|
||||
|
||||
@@ -61,6 +61,21 @@ const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: fa
|
||||
win.show()
|
||||
```
|
||||
|
||||
## Windows Control Overlay
|
||||
|
||||
On macOS, when using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` or using one of the `titleBarStyle`s described above so
|
||||
that the traffic lights are visible, you can access the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and
|
||||
[CSS Environment Variables][overlay-css-env-vars] by setting the `titleBarOverlay` option to true:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow({
|
||||
titleBarStyle: 'hiddenInset',
|
||||
titleBarOverlay: true
|
||||
})
|
||||
win.show()
|
||||
```
|
||||
|
||||
## Transparent window
|
||||
|
||||
By setting the `transparent` option to `true`, you can also make the frameless
|
||||
@@ -186,3 +201,5 @@ behave correctly on all platforms you should never use a custom context menu on
|
||||
draggable areas.
|
||||
|
||||
[ignore-mouse-events]: browser-window.md#winsetignoremouseeventsignore-options
|
||||
[overlay-javascript-apis]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#javascript-apis
|
||||
[overlay-css-env-vars]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#css-environment-variables
|
||||
|
||||
@@ -40,6 +40,8 @@ ipcMain.on('synchronous-message', (event, arg) => {
|
||||
|
||||
```javascript
|
||||
// In renderer process (web page).
|
||||
// NB. Electron APIs are only accessible from preload, unless contextIsolation is disabled.
|
||||
// See https://www.electronjs.org/docs/tutorial/process-model#preload-scripts for more details.
|
||||
const { ipcRenderer } = require('electron')
|
||||
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"
|
||||
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
# `sandbox` Option
|
||||
|
||||
> Create a browser window with a sandboxed renderer. With this
|
||||
option enabled, the renderer must communicate via IPC to the main process in order to access node APIs.
|
||||
|
||||
One of the key security features of Chromium is that all blink rendering/JavaScript
|
||||
code is executed within a sandbox. This sandbox uses OS-specific features to ensure
|
||||
that exploits in the renderer process cannot harm the system.
|
||||
|
||||
In other words, when the sandbox is enabled, the renderers can only make changes
|
||||
to the system by delegating tasks to the main process via IPC.
|
||||
[Here's](https://www.chromium.org/developers/design-documents/sandbox) more
|
||||
information about the sandbox.
|
||||
|
||||
Since a major feature in Electron is the ability to run Node.js in the
|
||||
renderer process (making it easier to develop desktop applications using web
|
||||
technologies), the sandbox is disabled by electron. This is because
|
||||
most Node.js APIs require system access. `require()` for example, is not
|
||||
possible without file system permissions, which are not available in a sandboxed
|
||||
environment.
|
||||
|
||||
Usually this is not a problem for desktop applications since the code is always
|
||||
trusted, but it makes Electron less secure than Chromium for displaying
|
||||
untrusted web content. For applications that require more security, the
|
||||
`sandbox` flag will force Electron to spawn a classic Chromium renderer that is
|
||||
compatible with the sandbox.
|
||||
|
||||
A sandboxed renderer doesn't have a Node.js environment running and doesn't
|
||||
expose Node.js JavaScript APIs to client code. The only exception is the preload script,
|
||||
which has access to a subset of the Electron renderer API.
|
||||
|
||||
Another difference is that sandboxed renderers don't modify any of the default
|
||||
JavaScript APIs. Consequently, some APIs such as `window.open` will work as they
|
||||
do in Chromium (i.e. they do not return a [`BrowserWindowProxy`](browser-window-proxy.md)).
|
||||
|
||||
## Example
|
||||
|
||||
To create a sandboxed window, pass `sandbox: true` to `webPreferences`:
|
||||
|
||||
```js
|
||||
let win
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
sandbox: true
|
||||
}
|
||||
})
|
||||
win.loadURL('http://google.com')
|
||||
})
|
||||
```
|
||||
|
||||
In the above code the [`BrowserWindow`](browser-window.md) that was created has Node.js disabled and can communicate
|
||||
only via IPC. The use of this option stops Electron from creating a Node.js runtime in the renderer. Also,
|
||||
within this new window `window.open` follows the native behavior (by default Electron creates a [`BrowserWindow`](browser-window.md)
|
||||
and returns a proxy to this via `window.open`).
|
||||
|
||||
[`app.enableSandbox`](app.md#appenablesandbox) can be used to force `sandbox: true` for all `BrowserWindow` instances.
|
||||
|
||||
```js
|
||||
let win
|
||||
app.enableSandbox()
|
||||
app.whenReady().then(() => {
|
||||
// no need to pass `sandbox: true` since `app.enableSandbox()` was called.
|
||||
win = new BrowserWindow()
|
||||
win.loadURL('http://google.com')
|
||||
})
|
||||
```
|
||||
|
||||
## Preload
|
||||
|
||||
An app can make customizations to sandboxed renderers using a preload script.
|
||||
Here's an example:
|
||||
|
||||
```js
|
||||
let win
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
sandbox: true,
|
||||
preload: path.join(app.getAppPath(), 'preload.js')
|
||||
}
|
||||
})
|
||||
win.loadURL('http://google.com')
|
||||
})
|
||||
```
|
||||
|
||||
and preload.js:
|
||||
|
||||
```js
|
||||
// This file is loaded whenever a javascript context is created. It runs in a
|
||||
// private scope that can access a subset of Electron renderer APIs. Without
|
||||
// contextIsolation enabled, it's possible to accidentally leak privileged
|
||||
// globals like ipcRenderer to web content.
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
const defaultWindowOpen = window.open
|
||||
|
||||
window.open = function customWindowOpen (url, ...args) {
|
||||
ipcRenderer.send('report-window-open', location.origin, url, args)
|
||||
return defaultWindowOpen(url + '?from_electron=1', ...args)
|
||||
}
|
||||
```
|
||||
|
||||
Important things to notice in the preload script:
|
||||
|
||||
- Even though the sandboxed renderer doesn't have Node.js running, it still has
|
||||
access to a limited node-like environment: `Buffer`, `process`, `setImmediate`,
|
||||
`clearImmediate` and `require` are available.
|
||||
- The preload script must be contained in a single script, but it is possible to have
|
||||
complex preload code composed with multiple modules by using a tool like
|
||||
webpack or browserify. An example of using browserify is below.
|
||||
|
||||
To create a browserify bundle and use it as a preload script, something like
|
||||
the following should be used:
|
||||
|
||||
```sh
|
||||
browserify preload/index.js \
|
||||
-x electron \
|
||||
--insert-global-vars=__filename,__dirname -o preload.js
|
||||
```
|
||||
|
||||
The `-x` flag should be used with any required module that is already exposed in
|
||||
the preload scope, and tells browserify to use the enclosing `require` function
|
||||
for it. `--insert-global-vars` will ensure that `process`, `Buffer` and
|
||||
`setImmediate` are also taken from the enclosing scope(normally browserify
|
||||
injects code for those).
|
||||
|
||||
Currently the `require` function provided in the preload scope exposes the
|
||||
following modules:
|
||||
|
||||
- `electron`
|
||||
- `crashReporter`
|
||||
- `desktopCapturer`
|
||||
- `ipcRenderer`
|
||||
- `nativeImage`
|
||||
- `webFrame`
|
||||
- `events`
|
||||
- `timers`
|
||||
- `url`
|
||||
|
||||
More may be added as needed to expose more Electron APIs in the sandbox.
|
||||
|
||||
## Rendering untrusted content
|
||||
|
||||
Rendering untrusted content in Electron is still somewhat uncharted territory,
|
||||
though some apps are finding success (e.g. Beaker Browser). Our goal is to get
|
||||
as close to Chrome as we can in terms of the security of sandboxed content, but
|
||||
ultimately we will always be behind due to a few fundamental issues:
|
||||
|
||||
1. We do not have the dedicated resources or expertise that Chromium has to
|
||||
apply to the security of its product. We do our best to make use of what we
|
||||
have, to inherit everything we can from Chromium, and to respond quickly to
|
||||
security issues, but Electron cannot be as secure as Chromium without the
|
||||
resources that Chromium is able to dedicate.
|
||||
2. Some security features in Chrome (such as Safe Browsing and Certificate
|
||||
Transparency) require a centralized authority and dedicated servers, both of
|
||||
which run counter to the goals of the Electron project. As such, we disable
|
||||
those features in Electron, at the cost of the associated security they
|
||||
would otherwise bring.
|
||||
3. There is only one Chromium, whereas there are many thousands of apps built
|
||||
on Electron, all of which behave slightly differently. Accounting for those
|
||||
differences can yield a huge possibility space, and make it challenging to
|
||||
ensure the security of the platform in unusual use cases.
|
||||
4. We can't push security updates to users directly, so we rely on app vendors
|
||||
to upgrade the version of Electron underlying their app in order for
|
||||
security updates to reach users.
|
||||
|
||||
Here are some things to consider before rendering untrusted content:
|
||||
|
||||
- A preload script can accidentally leak privileged APIs to untrusted code,
|
||||
unless [`contextIsolation`](../tutorial/security.md#3-enable-context-isolation-for-remote-content)
|
||||
is also enabled.
|
||||
- Some bug in the V8 engine may allow malicious code to access the renderer
|
||||
preload APIs, effectively granting full access to the system through the
|
||||
`remote` module. Therefore, it is highly recommended to [disable the `remote`
|
||||
module](../tutorial/security.md#15-disable-the-remote-module).
|
||||
If disabling is not feasible, you should selectively [filter the `remote`
|
||||
module](../tutorial/security.md#16-filter-the-remote-module).
|
||||
- While we make our best effort to backport Chromium security fixes to older
|
||||
versions of Electron, we do not make a guarantee that every fix will be
|
||||
backported. Your best chance at staying secure is to be on the latest stable
|
||||
version of Electron.
|
||||
@@ -13,7 +13,7 @@ either process type.
|
||||
|
||||
The basic rule is: if a module is [GUI][gui] or low-level system related, then
|
||||
it should be only available in the main process. You need to be familiar with
|
||||
the concept of [main process vs. renderer process](../tutorial/quick-start.md#main-and-renderer-processes)
|
||||
the concept of main process vs. renderer process
|
||||
scripts to be able to use those modules.
|
||||
|
||||
The main process script is like a normal Node.js script:
|
||||
@@ -43,8 +43,6 @@ extra ability to use node modules if `nodeIntegration` is enabled:
|
||||
</html>
|
||||
```
|
||||
|
||||
To run your app, read [Run your app](../tutorial/quick-start.md#run-your-application).
|
||||
|
||||
## Destructuring assignment
|
||||
|
||||
As of 0.37, you can use
|
||||
|
||||
@@ -1281,8 +1281,7 @@ Inserts `text` to the focused element.
|
||||
* `text` String - Content to be searched, must not be empty.
|
||||
* `options` Object (optional)
|
||||
* `forward` Boolean (optional) - Whether to search forward or backward, defaults to `true`.
|
||||
* `findNext` Boolean (optional) - Whether the operation is first request or a follow up,
|
||||
defaults to `false`.
|
||||
* `findNext` Boolean (optional) - Whether to begin a new text finding session with this request. Should be `true` for initial requests, and `false` for follow-up requests. Defaults to `false`.
|
||||
* `matchCase` Boolean (optional) - Whether search should be case-sensitive,
|
||||
defaults to `false`.
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ The following methods are available on instances of `WebRequest`:
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `resourceType` String - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
@@ -98,7 +98,7 @@ Some examples of valid `urls`:
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `resourceType` String - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
* `requestHeaders` Record<string, string>
|
||||
@@ -127,7 +127,7 @@ The `callback` has to be called with a `response` object.
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `resourceType` String - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
* `requestHeaders` Record<string, string>
|
||||
@@ -149,12 +149,11 @@ response are visible by the time this listener is fired.
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `resourceType` String - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
* `statusLine` String
|
||||
* `statusCode` Integer
|
||||
* `requestHeaders` Record<string, string>
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `callback` Function
|
||||
* `headersReceivedResponse` Object
|
||||
@@ -183,7 +182,7 @@ The `callback` has to be called with a `response` object.
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `resourceType` String - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
@@ -209,7 +208,7 @@ and response headers are available.
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `resourceType` String - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
* `redirectURL` String
|
||||
@@ -236,7 +235,7 @@ redirect is about to occur.
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `resourceType` String - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
@@ -261,7 +260,7 @@ completed.
|
||||
* `webContentsId` Integer (optional)
|
||||
* `webContents` WebContents (optional)
|
||||
* `frame` WebFrameMain (optional)
|
||||
* `resourceType` String
|
||||
* `resourceType` String - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` String
|
||||
* `timestamp` Double
|
||||
* `fromCache` Boolean
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Electron's `webview` tag is based on [Chromium's `webview`][chrome-webview], which
|
||||
is undergoing dramatic architectural changes. This impacts the stability of `webviews`,
|
||||
including rendering, navigation, and event routing. We currently recommend to not
|
||||
use the `webview` tag and to consider alternatives, like `iframe`, Electron's `BrowserView`,
|
||||
use the `webview` tag and to consider alternatives, like `iframe`, [Electron's `BrowserView`](browser-view.md),
|
||||
or an architecture that avoids embedded content altogether.
|
||||
|
||||
## Enabling
|
||||
@@ -506,8 +506,7 @@ Inserts `text` to the focused element.
|
||||
* `text` String - Content to be searched, must not be empty.
|
||||
* `options` Object (optional)
|
||||
* `forward` Boolean (optional) - Whether to search forward or backward, defaults to `true`.
|
||||
* `findNext` Boolean (optional) - Whether the operation is first request or a follow up,
|
||||
defaults to `false`.
|
||||
* `findNext` Boolean (optional) - Whether to begin a new text finding session with this request. Should be `true` for initial requests, and `false` for follow-up requests. Defaults to `false`.
|
||||
* `matchCase` Boolean (optional) - Whether search should be case-sensitive,
|
||||
defaults to `false`.
|
||||
|
||||
@@ -710,6 +709,10 @@ Corresponds to the points in time when the spinner of the tab starts spinning.
|
||||
|
||||
Corresponds to the points in time when the spinner of the tab stops spinning.
|
||||
|
||||
### Event: 'did-attach'
|
||||
|
||||
Fired when attached to the embedder web contents.
|
||||
|
||||
### Event: 'dom-ready'
|
||||
|
||||
Fired when document in the given frame is loaded.
|
||||
|
||||
@@ -6,15 +6,16 @@ untrusted content within a renderer. Windows can be created from the renderer in
|
||||
* clicking on links or submitting forms adorned with `target=_blank`
|
||||
* JavaScript calling `window.open()`
|
||||
|
||||
For same-origin content, the new window is created within the same process,
|
||||
enabling the parent to access the child window directly. This can be very
|
||||
useful for app sub-windows that act as preference panels, or similar, as the
|
||||
parent can render to the sub-window directly, as if it were a `div` in the
|
||||
parent. This is the same behavior as in the browser.
|
||||
In non-sandboxed renderers, or when `nativeWindowOpen` is false (the default), this results in the creation of a
|
||||
[`BrowserWindowProxy`](browser-window-proxy.md), a light wrapper around
|
||||
`BrowserWindow`.
|
||||
|
||||
When `nativeWindowOpen` is set to false, `window.open` instead results in the
|
||||
creation of a [`BrowserWindowProxy`](browser-window-proxy.md), a light wrapper
|
||||
around `BrowserWindow`.
|
||||
However, when the `sandbox` (or directly, `nativeWindowOpen`) option is set, a
|
||||
`Window` instance is created, as you'd expect in the browser. For same-origin
|
||||
content, the new window is created within the same process, enabling the parent
|
||||
to access the child window directly. This can be very useful for app sub-windows that act
|
||||
as preference panels, or similar, as the parent can render to the sub-window
|
||||
directly, as if it were a `div` in the parent.
|
||||
|
||||
Electron pairs this native Chrome `Window` with a BrowserWindow under the hood.
|
||||
You can take advantage of all the customization available when creating a
|
||||
@@ -67,50 +68,18 @@ window.open('https://github.com', '_blank', 'top=500,left=200,frame=false,nodeIn
|
||||
|
||||
To customize or cancel the creation of the window, you can optionally set an
|
||||
override handler with `webContents.setWindowOpenHandler()` from the main
|
||||
process. Returning `{ action: 'deny' }` cancels the window. Returning `{
|
||||
action: 'allow', overrideBrowserWindowOptions: { ... } }` will allow opening
|
||||
the window and setting the `BrowserWindowConstructorOptions` to be used when
|
||||
creating the window. Note that this is more powerful than passing options
|
||||
through the feature string, as the renderer has more limited privileges in
|
||||
deciding security preferences than the main process.
|
||||
|
||||
### Native `Window` example
|
||||
|
||||
```javascript
|
||||
// main.js
|
||||
const mainWindow = new BrowserWindow()
|
||||
|
||||
// In this example, only windows with the `about:blank` url will be created.
|
||||
// All other urls will be blocked.
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
if (url === 'about:blank') {
|
||||
return {
|
||||
frame: false,
|
||||
fullscreenable: false,
|
||||
backgroundColor: 'black',
|
||||
webPreferences: {
|
||||
preload: 'my-child-window-preload-script.js'
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
```
|
||||
|
||||
```javascript
|
||||
// renderer process (mainWindow)
|
||||
const childWindow = window.open('', 'modal')
|
||||
childWindow.document.write('<h1>Hello</h1>')
|
||||
```
|
||||
process. Returning `false` cancels the window, while returning an object sets
|
||||
the `BrowserWindowConstructorOptions` used when creating the window. Note that
|
||||
this is more powerful than passing options through the feature string, as the
|
||||
renderer has more limited privileges in deciding security preferences than the
|
||||
main process.
|
||||
|
||||
### `BrowserWindowProxy` example
|
||||
|
||||
```javascript
|
||||
|
||||
// main.js
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: { nativeWindowOpen: false }
|
||||
})
|
||||
const mainWindow = new BrowserWindow()
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
if (url.startsWith('https://github.com/')) {
|
||||
@@ -132,3 +101,39 @@ mainWindow.webContents.on('did-create-window', (childWindow) => {
|
||||
const windowProxy = window.open('https://github.com/', null, 'minimizable=false')
|
||||
windowProxy.postMessage('hi', '*')
|
||||
```
|
||||
|
||||
### Native `Window` example
|
||||
|
||||
```javascript
|
||||
// main.js
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
nativeWindowOpen: true
|
||||
}
|
||||
})
|
||||
|
||||
// In this example, only windows with the `about:blank` url will be created.
|
||||
// All other urls will be blocked.
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
if (url === 'about:blank') {
|
||||
return {
|
||||
action: 'allow',
|
||||
overrideBrowserWindowOptions: {
|
||||
frame: false,
|
||||
fullscreenable: false,
|
||||
backgroundColor: 'black',
|
||||
webPreferences: {
|
||||
preload: 'my-child-window-preload-script.js'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return { action: 'deny' }
|
||||
})
|
||||
```
|
||||
|
||||
```javascript
|
||||
// renderer process (mainWindow)
|
||||
const childWindow = window.open('', 'modal')
|
||||
childWindow.document.write('<h1>Hello</h1>')
|
||||
```
|
||||
|
||||
@@ -12,6 +12,18 @@ This document uses the following convention to categorize breaking changes:
|
||||
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
|
||||
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
|
||||
|
||||
## Planned Breaking API Changes (15.0)
|
||||
|
||||
### Default Changed: `nativeWindowOpen` defaults to `true`
|
||||
|
||||
Prior to Electron 15, `window.open` was by default shimmed to use
|
||||
`BrowserWindowProxy`. This meant that `window.open('about:blank')` did not work
|
||||
to open synchronously scriptable child windows, among other incompatibilities.
|
||||
`nativeWindowOpen: true` is no longer experimental, and is now the default.
|
||||
|
||||
See the documentation for [window.open in Electron](api/window-open.md)
|
||||
for more details.
|
||||
|
||||
## Planned Breaking API Changes (14.0)
|
||||
|
||||
### Removed: `app.allowRendererProcessReuse`
|
||||
@@ -43,16 +55,6 @@ ensure your code works with this property enabled. It has been enabled by defau
|
||||
|
||||
You will be affected by this change if you use either `webFrame.executeJavaScript` or `webFrame.executeJavaScriptInIsolatedWorld`. You will need to ensure that values returned by either of those methods are supported by the [Context Bridge API](api/context-bridge.md#parameter--error--return-type-support) as these methods use the same value passing semantics.
|
||||
|
||||
### Default Changed: `nativeWindowOpen` defaults to `true`
|
||||
|
||||
Prior to Electron 14, `window.open` was by default shimmed to use
|
||||
`BrowserWindowProxy`. This meant that `window.open('about:blank')` did not work
|
||||
to open synchronously scriptable child windows, among other incompatibilities.
|
||||
`nativeWindowOpen` is no longer experimental, and is now the default.
|
||||
|
||||
See the documentation for [window.open in Electron](api/window-open.md)
|
||||
for more details.
|
||||
|
||||
### Removed: BrowserWindowConstructorOptions inheriting from parent windows
|
||||
|
||||
Prior to Electron 14, windows opened with `window.open` would inherit
|
||||
|
||||
@@ -10,12 +10,12 @@ files, you need to have built Electron so that it knows which compiler flags
|
||||
were used. There is one required option for the script `--output-dir`, which
|
||||
tells the script which build directory to pull the compilation information
|
||||
from. A typical usage would be:
|
||||
`npm run lint:clang-tiy --out-dir ../out/Testing`
|
||||
`npm run lint:clang-tidy --out-dir ../out/Testing`
|
||||
|
||||
With no filenames provided, all C/C++/Objective-C files will be checked.
|
||||
You can provide a list of files to be checked by passing the filenames after
|
||||
the options:
|
||||
`npm run lint:clang-tiy --out-dir ../out/Testing shell/browser/api/electron_api_app.cc`
|
||||
`npm run lint:clang-tidy --out-dir ../out/Testing shell/browser/api/electron_api_app.cc`
|
||||
|
||||
While `clang-tidy` has a
|
||||
[long list](https://clang.llvm.org/extra/clang-tidy/checks/list.html)
|
||||
|
||||
@@ -25,7 +25,7 @@ You can run `npm run lint` to show any style issues detected by `cpplint` and
|
||||
## C++ and Python
|
||||
|
||||
For C++ and Python, we follow Chromium's [Coding
|
||||
Style](https://www.chromium.org/developers/coding-style). You can use
|
||||
Style](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/styleguide.md). You can use
|
||||
[clang-format](clang-format.md) to format the C++ code automatically. There is
|
||||
also a script `script/cpplint.py` to check whether all files conform.
|
||||
|
||||
|
||||
@@ -7,12 +7,9 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<a href="#" id="drag">Drag me</a>
|
||||
<p>Drag the boxes below to somewhere in your OS (Finder/Explorer, Desktop, etc.) to copy an example markdown file.</p>
|
||||
<div style="border:2px solid black;border-radius:3px;padding:5px;display:inline-block" draggable="true" id="drag1">Drag me - File 1</div>
|
||||
<div style="border:2px solid black;border-radius:3px;padding:5px;display:inline-block" draggable="true" id="drag2">Drag me - File 2</div>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
const { app, BrowserWindow, ipcMain, nativeImage, NativeImage } = require('electron')
|
||||
const fs = require('fs');
|
||||
const http = require('http');
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const https = require('https')
|
||||
|
||||
function createWindow () {
|
||||
function createWindow() {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
const iconName = 'iconForDragAndDrop.png';
|
||||
const icon = fs.createWriteStream(`${process.cwd()}/${iconName}`);
|
||||
http.get('http://img.icons8.com/ios/452/drag-and-drop.png', (response) => {
|
||||
|
||||
const iconName = path.join(__dirname, 'iconForDragAndDrop.png');
|
||||
const icon = fs.createWriteStream(iconName);
|
||||
|
||||
// Create a new file to copy - you can also copy existing files.
|
||||
fs.writeFileSync(path.join(__dirname, 'drag-and-drop-1.md'), '# First file to test drag and drop')
|
||||
fs.writeFileSync(path.join(__dirname, 'drag-and-drop-2.md'), '# Second file to test drag and drop')
|
||||
|
||||
https.get('https://img.icons8.com/ios/452/drag-and-drop.png', (response) => {
|
||||
response.pipe(icon);
|
||||
});
|
||||
|
||||
@@ -23,8 +30,8 @@ app.whenReady().then(createWindow)
|
||||
|
||||
ipcMain.on('ondragstart', (event, filePath) => {
|
||||
event.sender.startDrag({
|
||||
file: filePath,
|
||||
icon: `${process.cwd()}/${iconName}`
|
||||
file: path.join(__dirname, filePath),
|
||||
icon: iconName,
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
8
docs/fiddles/features/drag-and-drop/preload.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
startDrag: (fileName) => {
|
||||
ipcRenderer.send('ondragstart', fileName)
|
||||
}
|
||||
})
|
||||
@@ -1,9 +1,9 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
const fs = require('fs')
|
||||
|
||||
document.getElementById('drag').ondragstart = (event) => {
|
||||
const fileName = 'drag-and-drop.md'
|
||||
fs.writeFileSync(fileName, '# Test drag and drop');
|
||||
document.getElementById('drag1').ondragstart = (event) => {
|
||||
event.preventDefault()
|
||||
ipcRenderer.send('ondragstart', process.cwd() + `/${fileName}`)
|
||||
window.electron.startDrag('drag-and-drop-1.md')
|
||||
}
|
||||
|
||||
document.getElementById('drag2').ondragstart = (event) => {
|
||||
event.preventDefault()
|
||||
window.electron.startDrag('drag-and-drop-2.md')
|
||||
}
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<p>Hit Alt+Ctrl+I on Windows or Opt+Cmd+I on Mac to see a message printed to the console.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,9 +4,6 @@ function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
<p>Hit Ctrl+I to see a message printed to the console.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } })
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
|
||||
win.loadFile('index.html')
|
||||
win.webContents.on('before-input-event', (event, input) => {
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<p>Hit Alt+Shift+I on Windows, or Opt+Cmd+I on mac to see a message printed to the console.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,9 +4,6 @@ function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
|
||||
17
docs/fiddles/features/keyboard-shortcuts/web-apis/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
|
||||
<p>Hit any key with this window focused to see it captured here.</p>
|
||||
<div><span>Last Key Pressed: </span><span id="last-keypress"></span></div>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
35
docs/fiddles/features/keyboard-shortcuts/web-apis/main.js
Normal file
@@ -0,0 +1,35 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const {app, BrowserWindow} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
function handleKeyPress (event) {
|
||||
// You can put code here to handle the keypress.
|
||||
document.getElementById("last-keypress").innerText = event.key
|
||||
console.log(`You pressed ${event.key}`)
|
||||
}
|
||||
|
||||
window.addEventListener('keyup', handleKeyPress, true)
|
||||
@@ -1,11 +1,12 @@
|
||||
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -21,20 +22,22 @@ function createWindow () {
|
||||
})
|
||||
|
||||
ipcMain.handle('dark-mode:system', () => {
|
||||
nativeTheme.themeSouce = 'system'
|
||||
nativeTheme.themeSource = 'system'
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
6
docs/fiddles/features/macos-dark-mode/preload.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('darkMode', {
|
||||
toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
|
||||
system: () => ipcRenderer.invoke('dark-mode:system')
|
||||
})
|
||||
@@ -1,11 +1,9 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
|
||||
const isDarkMode = await ipcRenderer.invoke('dark-mode:toggle')
|
||||
const isDarkMode = await window.darkMode.toggle()
|
||||
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
|
||||
})
|
||||
|
||||
document.getElementById('reset-to-system').addEventListener('click', async () => {
|
||||
await ipcRenderer.invoke('dark-mode:system')
|
||||
await window.darkMode.system()
|
||||
document.getElementById('theme-source').innerHTML = 'System'
|
||||
})
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<p>Right click the dock icon to see the custom menu options.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,9 +4,6 @@ function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
@@ -27,7 +24,9 @@ const dockMenu = Menu.buildFromTemplate([
|
||||
])
|
||||
|
||||
app.whenReady().then(() => {
|
||||
app.dock.setMenu(dockMenu)
|
||||
if (process.platform === 'darwin') {
|
||||
app.dock.setMenu(dockMenu)
|
||||
}
|
||||
}).then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<p>After launching this application, you should see the system notification.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -3,21 +3,17 @@ const { app, BrowserWindow, Notification } = require('electron')
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
const NOTIFICATION_TITLE = 'Basic Notification'
|
||||
const NOTIFICATION_BODY = 'Notification from the Main process'
|
||||
|
||||
function showNotification () {
|
||||
const notification = {
|
||||
title: 'Basic Notification',
|
||||
body: 'Notification from the Main process'
|
||||
}
|
||||
new Notification(notification).show()
|
||||
new Notification({ title: NOTIFICATION_TITLE, body: NOTIFICATION_BODY }).show()
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow).then(showNotification)
|
||||
|
||||
@@ -7,11 +7,9 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<p>After launching this application, you should see the system notification.</p>
|
||||
<p id="output">Click it to see the effect in this interface.</p>
|
||||
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -3,10 +3,7 @@ const { app, BrowserWindow } = require('electron')
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const myNotification = new Notification('Title', {
|
||||
body: 'Notification from the Renderer process'
|
||||
})
|
||||
const NOTIFICATION_TITLE = 'Title'
|
||||
const NOTIFICATION_BODY = 'Notification from the Renderer process. Click to log to console.'
|
||||
const CLICK_MESSAGE = 'Notification clicked!'
|
||||
|
||||
myNotification.onclick = () => {
|
||||
console.log('Notification clicked')
|
||||
}
|
||||
new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY })
|
||||
.onclick = () => document.getElementById("output").innerText = CLICK_MESSAGE
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +1,6 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
app.disableHardwareAcceleration()
|
||||
|
||||
@@ -12,7 +13,7 @@ app.whenReady().then(() => {
|
||||
fs.writeFileSync('ex.png', image.toPNG())
|
||||
})
|
||||
win.webContents.setFrameRate(60)
|
||||
console.log(`The screenshot has been successfully saved to ${process.cwd()}/ex.png`)
|
||||
console.log(`The screenshot has been successfully saved to ${path.join(process.cwd(), 'ex.png')}`)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
|
||||
13
docs/fiddles/features/online-detection/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Connection status: <strong id='status'></strong></h1>
|
||||
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
26
docs/fiddles/features/online-detection/main.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
function createWindow () {
|
||||
const onlineStatusWindow = new BrowserWindow({
|
||||
width: 300,
|
||||
height: 200
|
||||
})
|
||||
|
||||
onlineStatusWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
const { app, BrowserWindow, ipcMain } = require('electron')
|
||||
|
||||
let onlineStatusWindow
|
||||
|
||||
app.whenReady().then(() => {
|
||||
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false, webPreferences: { nodeIntegration: true } })
|
||||
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
|
||||
})
|
||||
|
||||
ipcMain.on('online-status-changed', (event, status) => {
|
||||
console.log(status)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
@@ -1,7 +0,0 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
const updateOnlineStatus = () => { ipcRenderer.send('online-status-changed', navigator.onLine ? 'online' : 'offline') }
|
||||
|
||||
window.addEventListener('online', updateOnlineStatus)
|
||||
window.addEventListener('offline', updateOnlineStatus)
|
||||
|
||||
updateOnlineStatus()
|
||||
8
docs/fiddles/features/online-detection/renderer.js
Normal file
@@ -0,0 +1,8 @@
|
||||
function onlineStatusIndicator () {
|
||||
document.getElementById('status').innerHTML = navigator.onLine ? 'online' : 'offline'
|
||||
}
|
||||
|
||||
window.addEventListener('online', onlineStatusIndicator)
|
||||
window.addEventListener('offline', onlineStatusIndicator)
|
||||
|
||||
onlineStatusIndicator()
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,20 +0,0 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let onlineStatusWindow
|
||||
|
||||
app.whenReady().then(() => {
|
||||
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false })
|
||||
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
@@ -1,6 +0,0 @@
|
||||
const alertOnlineStatus = () => { window.alert(navigator.onLine ? 'online' : 'offline') }
|
||||
|
||||
window.addEventListener('online', alertOnlineStatus)
|
||||
window.addEventListener('offline', alertOnlineStatus)
|
||||
|
||||
alertOnlineStatus()
|
||||
@@ -7,10 +7,9 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
</p>
|
||||
<p>Keep an eye on the dock (Mac) or taskbar (Windows, Unity) for this application!</p>
|
||||
<p>It should indicate a progress that advances from 0 to 100%.</p>
|
||||
<p>It should then show indeterminate (Windows) or pin at 100% (other operating systems)
|
||||
briefly and then loop.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,21 +1,39 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let progressInterval
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
win.setProgressBar(0.5)
|
||||
}
|
||||
|
||||
const INCREMENT = 0.03
|
||||
const INTERVAL_DELAY = 100 // ms
|
||||
|
||||
let c = 0
|
||||
progressInterval = setInterval(() => {
|
||||
// update progress bar to next value
|
||||
// values between 0 and 1 will show progress, >1 will show indeterminate or stick at 100%
|
||||
win.setProgressBar(c)
|
||||
|
||||
// increment or reset progress bar
|
||||
if (c < 2) {
|
||||
c += INCREMENT
|
||||
} else {
|
||||
c = (-INCREMENT * 5) // reset to a bit less than 0 to show reset state
|
||||
}
|
||||
}, INTERVAL_DELAY)
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// before the app is terminated, clear both timers
|
||||
app.on('before-quit', () => {
|
||||
clearInterval(progressInterval)
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<title>Recent Documents</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<h1>Recent Documents</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
Right click on the app icon to see recent documents.
|
||||
You should see `recently-used.md` added to the list of recent files
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -5,17 +5,15 @@ const path = require('path')
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
const fileName = 'recently-used.md'
|
||||
fs.writeFile(fileName, 'Lorem Ipsum', () => {
|
||||
app.addRecentDocument(path.join(process.cwd(), `${fileName}`))
|
||||
app.addRecentDocument(path.join(__dirname, fileName))
|
||||
})
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
<link rel="stylesheet" type="text/css" href="./styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
<p>
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
Click on the title with the <pre>Command</pre> or <pre>Control</pre> key pressed.
|
||||
You should see a popup with the represented file at the top.
|
||||
</p>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,10 +4,7 @@ const os = require('os');
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
|
||||
@@ -16,91 +16,12 @@
|
||||
<p>
|
||||
Open the
|
||||
<a href="https://electronjs.org/docs/api/tray">
|
||||
full API documentation (opens in new window)
|
||||
full API documentation
|
||||
</a>
|
||||
in your browser.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<button id="put-in-tray">View Demo</button>
|
||||
<span id="tray-countdown"></span>
|
||||
</div>
|
||||
<p>
|
||||
The demo button sends a message to the main process using the
|
||||
<code>ipc</code> module. In the main process the app is told to
|
||||
place an icon, with a context menu, in the tray.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In this example the tray icon can be removed by clicking 'Remove' in
|
||||
the context menu or selecting the demo button again.
|
||||
</p>
|
||||
<h5>Main Process</h5>
|
||||
<pre>
|
||||
<code>
|
||||
const path = require('path')
|
||||
const {ipcMain, app, Menu, Tray} = require('electron')
|
||||
|
||||
let appIcon = null
|
||||
|
||||
ipcMain.on('put-in-tray', (event) => {
|
||||
const iconName = process.platform === 'win32' ? 'windows-icon.png' : 'iconTemplate.png'
|
||||
const iconPath = path.join(__dirname, iconName)
|
||||
appIcon = new Tray(iconPath)
|
||||
|
||||
const contextMenu = Menu.buildFromTemplate([{
|
||||
label: 'Remove',
|
||||
click: () => {
|
||||
event.sender.send('tray-removed')
|
||||
}
|
||||
}])
|
||||
|
||||
appIcon.setToolTip('Electron Demo in the tray.')
|
||||
appIcon.setContextMenu(contextMenu)
|
||||
})
|
||||
|
||||
ipcMain.on('remove-tray', () => {
|
||||
appIcon.destroy()
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (appIcon) appIcon.destroy()
|
||||
})
|
||||
</code>
|
||||
</pre>
|
||||
<h5>Renderer Process</h5>
|
||||
<pre>
|
||||
<code>
|
||||
const ipc = require('electron').ipcRenderer
|
||||
|
||||
const trayBtn = document.getElementById('put-in-tray')
|
||||
let trayOn = false
|
||||
|
||||
trayBtn.addEventListener('click', function (event) {
|
||||
if (trayOn) {
|
||||
trayOn = false
|
||||
document.getElementById('tray-countdown').innerHTML = ''
|
||||
ipc.send('remove-tray')
|
||||
} else {
|
||||
trayOn = true
|
||||
const message = 'Click demo again to remove.'
|
||||
document.getElementById('tray-countdown').innerHTML = message
|
||||
ipc.send('put-in-tray')
|
||||
}
|
||||
})
|
||||
// Tray removed from context menu on icon
|
||||
ipc.on('tray-removed', function () {
|
||||
ipc.send('remove-tray')
|
||||
trayOn = false
|
||||
document.getElementById('tray-countdown').innerHTML = ''
|
||||
})
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<div>
|
||||
<h2>ProTip</h2>
|
||||
<strong>Tray support in Linux.</strong>
|
||||
@@ -109,7 +30,7 @@ ipc.on('tray-removed', function () {
|
||||
will need to install <code>libappindicator1</code> to make the
|
||||
tray icon work. See the
|
||||
<a href="https://electronjs.org/docs/api/tray">
|
||||
full API documentation (opens in new window)
|
||||
full API documentation
|
||||
</a>
|
||||
for more details about using Tray on Linux.
|
||||
</p>
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
const { ipcRenderer, shell } = require('electron')
|
||||
|
||||
const trayBtn = document.getElementById('put-in-tray')
|
||||
const links = document.querySelectorAll('a[href]')
|
||||
|
||||
let trayOn = false
|
||||
|
||||
trayBtn.addEventListener('click', function (event) {
|
||||
if (trayOn) {
|
||||
trayOn = false
|
||||
document.getElementById('tray-countdown').innerHTML = ''
|
||||
ipcRenderer.send('remove-tray')
|
||||
} else {
|
||||
trayOn = true
|
||||
const message = 'Click demo again to remove.'
|
||||
document.getElementById('tray-countdown').innerHTML = message
|
||||
ipcRenderer.send('put-in-tray')
|
||||
}
|
||||
})
|
||||
// Tray removed from context menu on icon
|
||||
ipcRenderer.on('tray-removed', function () {
|
||||
ipcRenderer.send('remove-tray')
|
||||
trayOn = false
|
||||
document.getElementById('tray-countdown').innerHTML = ''
|
||||
})
|
||||
|
||||
Array.prototype.forEach.call(links, (link) => {
|
||||
const url = link.getAttribute('href')
|
||||
if (url.indexOf('http') === 0) {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -1,92 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>app.setAsDefaultProtocol Demo</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section>
|
||||
<header>
|
||||
<h1>
|
||||
Protocol Handler
|
||||
</h1>
|
||||
<h3>The <code>app</code> module provides methods for handling protocols.</h3>
|
||||
<p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a browser asks to be your default for viewing web pages.</p>
|
||||
<h1>App Default Protocol Demo</h1>
|
||||
|
||||
<p>Open the <a href="https://electronjs.org/docs/api/app">full app API documentation<span class="u-visible-to-screen-reader">(opens in new window)</span></a> in your browser.</p>
|
||||
</header>
|
||||
<p>The protocol API allows us to register a custom protocol and intercept existing protocol requests.</p>
|
||||
<p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a
|
||||
browser asks to be your default for viewing web pages.</p>
|
||||
|
||||
<div >
|
||||
<button id="open-in-browser" class="js-container-target demo-toggle-button">Launch current page in browser
|
||||
<div class="demo-meta u-avoid-clicks">Supports: Win, macOS <span class="demo-meta-divider">|</span> Process: Main</div>
|
||||
</button>
|
||||
<section id='open-app-link'>
|
||||
<a href="electron-api-demos://open">Now... launch the app from a web link</a>
|
||||
</section>
|
||||
<div >
|
||||
<p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app as the default for <code>electron-api-demos://</code>. The demo button above will launch a page in your default browser with a link. Click that link and it will re-launch this app.</p>
|
||||
<h5>Packaging</h5>
|
||||
<p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code> for the app is updated to include the new protocol handler. If you're using <code>electron-packager</code> then you can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this app is below.</p>
|
||||
<h5>Renderer Process</h5>
|
||||
<pre><code>
|
||||
const {shell} = require('electron')
|
||||
const path = require('path')
|
||||
const protocolHandlerBtn = document.getElementById('protocol-handler')
|
||||
protocolHandlerBtn.addEventListener('click', () => {
|
||||
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
|
||||
const pagePath = path.join('file://', pageDirectory, '../../sections/system/protocol-link.html')
|
||||
shell.openExternal(pagePath)
|
||||
})
|
||||
</code></pre>
|
||||
<h5>Main Process</h5>
|
||||
<pre><code>
|
||||
const {app, dialog} = require('electron')
|
||||
const path = require('path')
|
||||
<p>Open the <a href="https://www.electronjs.org/docs/api/protocol">full protocol API documentation</a> in your
|
||||
browser.</p>
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos')
|
||||
}
|
||||
-----
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
<h3>Demo</h3>
|
||||
<p>
|
||||
First: Launch current page in browser
|
||||
<button id="open-in-browser" class="js-container-target demo-toggle-button">
|
||||
Click to Launch Browser
|
||||
</button>
|
||||
</p>
|
||||
|
||||
</code></pre>
|
||||
<h5>macOS plist</h5>
|
||||
<pre><code>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>electron-api-demos</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Electron API Demos Protocol</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ElectronTeamID</key>
|
||||
<string>VEKTX9H2N7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
require('./renderer.js')
|
||||
</script>
|
||||
</section>
|
||||
<p>
|
||||
Then: Launch the app from a web link!
|
||||
<a href="electron-fiddle://open">Click here to launch the app</a>
|
||||
</p>
|
||||
|
||||
----
|
||||
|
||||
<p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app
|
||||
as the default for <code>electron-fiddle://</code>. The demo button above will launch a page in your default
|
||||
browser with a link. Click that link and it will re-launch this app.</p>
|
||||
|
||||
|
||||
<h3>Packaging</h3>
|
||||
<p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in
|
||||
development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code>
|
||||
for the app is updated to include the new protocol handler. If you're using <code>electron-packager</code> then you
|
||||
can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this
|
||||
app is below:</p>
|
||||
|
||||
<p>
|
||||
<h5>macOS plist</h5>
|
||||
<pre><code>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>electron-api-demos</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Electron API Demos Protocol</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ElectronTeamID</key>
|
||||
<string>VEKTX9H2N7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
</code>
|
||||
</pre>
|
||||
<p>
|
||||
|
||||
<!-- You can also require other files to run in this process -->
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -1,10 +1,39 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, dialog } = require('electron')
|
||||
const { app, BrowserWindow, ipcMain, shell } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
let mainWindow;
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle')
|
||||
}
|
||||
|
||||
const gotTheLock = app.requestSingleInstanceLock()
|
||||
|
||||
if (!gotTheLock) {
|
||||
app.quit()
|
||||
} else {
|
||||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isMinimized()) mainWindow.restore()
|
||||
mainWindow.focus()
|
||||
}
|
||||
})
|
||||
|
||||
// Create mainWindow, load the rest of the app, etc...
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
@@ -12,58 +41,23 @@ function createWindow () {
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos')
|
||||
}
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
// Handle window controls via IPC
|
||||
ipcMain.on('shell:open', () => {
|
||||
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
|
||||
const pagePath = path.join('file://', pageDirectory, 'index.html')
|
||||
shell.openExternal(pagePath)
|
||||
})
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// All of the Node.js APIs are available in the preload process.
|
||||
// It has the same sandbox as a Chrome extension.
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
// Set up context bridge between the renderer process and the main process
|
||||
contextBridge.exposeInMainWorld(
|
||||
'shell',
|
||||
{
|
||||
open: () => ipcRenderer.send('shell:open'),
|
||||
}
|
||||
)
|
||||
@@ -1,14 +1,8 @@
|
||||
const { shell } = require('electron')
|
||||
const path = require('path')
|
||||
// This file is required by the index.html file and will
|
||||
// be executed in the renderer process for that window.
|
||||
// All APIs exposed by the context bridge are available here.
|
||||
|
||||
const openInBrowserButton = document.getElementById('open-in-browser')
|
||||
const openAppLink = document.getElementById('open-app-link')
|
||||
// Hides openAppLink when loaded inside Electron
|
||||
openAppLink.style.display = 'none'
|
||||
|
||||
openInBrowserButton.addEventListener('click', () => {
|
||||
console.log('clicked')
|
||||
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
|
||||
const pagePath = path.join('file://', pageDirectory, 'index.html')
|
||||
shell.openExternal(pagePath)
|
||||
})
|
||||
// Binds the buttons to the context bridge API.
|
||||
document.getElementById('open-in-browser').addEventListener('click', () => {
|
||||
shell.open();
|
||||
});
|
||||
BIN
docs/images/chrome-processes.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
docs/images/connection-status.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 32 KiB |
0
docs/images/versioning-sketch-2.png
Executable file → Normal file
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
@@ -2,15 +2,14 @@
|
||||
|
||||
These are the guidelines for writing Electron documentation.
|
||||
|
||||
## Titles
|
||||
## Headings
|
||||
|
||||
* Each page must have a single `#`-level title at the top.
|
||||
* Chapters in the same page must have `##`-level titles.
|
||||
* Sub-chapters need to increase the number of `#` in the title according to
|
||||
* Chapters in the same page must have `##`-level headings.
|
||||
* Sub-chapters need to increase the number of `#` in the heading according to
|
||||
their nesting depth.
|
||||
* All words in the page's title must be capitalized, except for conjunctions
|
||||
like "of" and "and" .
|
||||
* Only the first word of a chapter title must be capitalized.
|
||||
* The page's title must follow [APA title case][title-case].
|
||||
* All chapters must follow [APA sentence case][sentence-case].
|
||||
|
||||
Using `Quick Start` as example:
|
||||
|
||||
@@ -44,12 +43,20 @@ For API references, there are exceptions to this rule.
|
||||
|
||||
## Markdown rules
|
||||
|
||||
This repository uses the [`markdownlint`][markdownlint] package to enforce consistent
|
||||
Markdown styling. For the exact rules, see the `.markdownlint.json` file in the root
|
||||
folder.
|
||||
|
||||
There are a few style guidelines that aren't covered by the linter rules:
|
||||
|
||||
<!--TODO(erickzhao): make sure this matches with the lint:markdownlint task-->
|
||||
* Use `sh` instead of `cmd` in code blocks (due to the syntax highlighter).
|
||||
* Lines should be wrapped at 80 columns.
|
||||
* Keep line lengths between 80 and 100 characters if possible for readability
|
||||
purposes.
|
||||
* No nesting lists more than 2 levels (due to the markdown renderer).
|
||||
* All `js` and `javascript` code blocks are linted with
|
||||
[standard-markdown](https://www.npmjs.com/package/standard-markdown).
|
||||
* For unordered lists, use asterisks instead of dashes
|
||||
* For unordered lists, use asterisks instead of dashes.
|
||||
|
||||
## Picking words
|
||||
|
||||
@@ -60,14 +67,15 @@ For API references, there are exceptions to this rule.
|
||||
|
||||
The following rules only apply to the documentation of APIs.
|
||||
|
||||
### Page title
|
||||
### Title and description
|
||||
|
||||
Each page must use the actual object name returned by `require('electron')`
|
||||
as the title, such as `BrowserWindow`, `autoUpdater`, and `session`.
|
||||
Each module's API doc must use the actual object name returned by `require('electron')`
|
||||
as its title (such as `BrowserWindow`, `autoUpdater`, and `session`).
|
||||
|
||||
Under the page title must be a one-line description starting with `>`.
|
||||
Directly under the page title, add a one-line description of the module
|
||||
as a markdown quote (beginning with `>`).
|
||||
|
||||
Using `session` as example:
|
||||
Using the `session` module as an example:
|
||||
|
||||
```markdown
|
||||
# session
|
||||
@@ -99,14 +107,19 @@ Using `autoUpdater` as an example:
|
||||
* API classes or classes that are part of modules must be listed under a
|
||||
`## Class: TheClassName` chapter.
|
||||
* One page can have multiple classes.
|
||||
* Constructors must be listed with `###`-level titles.
|
||||
* [Static Methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static) must be listed under a `### Static Methods` chapter.
|
||||
* [Instance Methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Prototype_methods) must be listed under an `### Instance Methods` chapter.
|
||||
* All methods that have a return value must start their description with "Returns `[TYPE]` - Return description"
|
||||
* If the method returns an `Object`, its structure can be specified using a colon followed by a newline then an unordered list of properties in the same style as function parameters.
|
||||
* Constructors must be listed with `###`-level headings.
|
||||
* [Static Methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static)
|
||||
must be listed under a `### Static Methods` chapter.
|
||||
* [Instance Methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Prototype_methods)
|
||||
must be listed under an `### Instance Methods` chapter.
|
||||
* All methods that have a return value must start their description with
|
||||
"Returns `[TYPE]` - [Return description]"
|
||||
* If the method returns an `Object`, its structure can be specified using a colon
|
||||
followed by a newline then an unordered list of properties in the same style as
|
||||
function parameters.
|
||||
* Instance Events must be listed under an `### Instance Events` chapter.
|
||||
* Instance Properties must be listed under an `### Instance Properties` chapter.
|
||||
* Instance properties must start with "A [Property Type] ..."
|
||||
* Instance Properties must start with "A [Property Type] ..."
|
||||
|
||||
Using the `Session` and `Cookies` classes as an example:
|
||||
|
||||
@@ -142,7 +155,7 @@ Using the `Session` and `Cookies` classes as an example:
|
||||
#### `cookies.get(filter, callback)`
|
||||
```
|
||||
|
||||
### Methods
|
||||
### Methods and their arguments
|
||||
|
||||
The methods chapter must be in the following form:
|
||||
|
||||
@@ -155,8 +168,12 @@ The methods chapter must be in the following form:
|
||||
...
|
||||
```
|
||||
|
||||
The title can be `###` or `####`-levels depending on whether it is a method of
|
||||
a module or a class.
|
||||
#### Heading level
|
||||
|
||||
The heading can be `###` or `####`-levels depending on whether the method
|
||||
belongs to a module or a class.
|
||||
|
||||
#### Function signature
|
||||
|
||||
For modules, the `objectName` is the module's name. For classes, it must be the
|
||||
name of the instance of the class, and must not be the same as the module's
|
||||
@@ -165,23 +182,33 @@ name.
|
||||
For example, the methods of the `Session` class under the `session` module must
|
||||
use `ses` as the `objectName`.
|
||||
|
||||
The optional arguments are notated by square brackets `[]` surrounding the optional argument
|
||||
as well as the comma required if this optional argument follows another
|
||||
Optional arguments are notated by square brackets `[]` surrounding the optional
|
||||
argument as well as the comma required if this optional argument follows another
|
||||
argument:
|
||||
|
||||
```sh
|
||||
```markdown
|
||||
required[, optional]
|
||||
```
|
||||
|
||||
Below the method is more detailed information on each of the arguments. The type
|
||||
of argument is notated by either the common types:
|
||||
#### Argument descriptions
|
||||
|
||||
* [`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)
|
||||
* [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)
|
||||
* [`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
|
||||
* [`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
|
||||
* [`Boolean`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
|
||||
* Or a custom type like Electron's [`WebContent`](api/web-contents.md)
|
||||
More detailed information on each of the arguments is noted in an unordered list
|
||||
below the method. The type of argument is notated by either JavaScript primitives
|
||||
(e.g. `String`, `Promise`, or `Object`), a custom API structure like Electron's
|
||||
[`Cookie`](api/structures/cookie.md), or the wildcard `any`.
|
||||
|
||||
If the argument is of type `Array`, use `[]` shorthand with the type of value
|
||||
inside the array (for example,`any[]` or `String[]`).
|
||||
|
||||
If the argument is of type `Promise`, parametrize the type with what the promise
|
||||
resolves to (for example, `Promise<void>` or `Promise<String>`).
|
||||
|
||||
If an argument can be of multiple types, separate the types with `|`.
|
||||
|
||||
The description for `Function` type arguments should make it clear how it may be
|
||||
called and list the types of the parameters that will be passed to it.
|
||||
|
||||
#### Platform-specific functionality
|
||||
|
||||
If an argument or a method is unique to certain platforms, those platforms are
|
||||
denoted using a space-delimited italicized list following the datatype. Values
|
||||
@@ -191,12 +218,6 @@ can be `macOS`, `Windows` or `Linux`.
|
||||
* `animate` Boolean (optional) _macOS_ _Windows_ - Animate the thing.
|
||||
```
|
||||
|
||||
`Array` type arguments must specify what elements the array may include in
|
||||
the description below.
|
||||
|
||||
The description for `Function` type arguments should make it clear how it may be
|
||||
called and list the types of the parameters that will be passed to it.
|
||||
|
||||
### Events
|
||||
|
||||
The events chapter must be in following form:
|
||||
@@ -211,8 +232,8 @@ Returns:
|
||||
...
|
||||
```
|
||||
|
||||
The title can be `###` or `####`-levels depending on whether it is an event of
|
||||
a module or a class.
|
||||
The heading can be `###` or `####`-levels depending on whether the event
|
||||
belongs to a module or a class.
|
||||
|
||||
The arguments of an event follow the same rules as methods.
|
||||
|
||||
@@ -226,9 +247,13 @@ The properties chapter must be in following form:
|
||||
...
|
||||
```
|
||||
|
||||
The title can be `###` or `####`-levels depending on whether it is a property of
|
||||
a module or a class.
|
||||
The heading can be `###` or `####`-levels depending on whether the property
|
||||
belongs to a module or a class.
|
||||
|
||||
## Documentation Translations
|
||||
## Documentation translations
|
||||
|
||||
See [electron/i18n](https://github.com/electron/i18n#readme)
|
||||
|
||||
[title-case]: https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case
|
||||
[sentence-case]: https://apastyle.apa.org/style-grammar-guidelines/capitalization/sentence-case
|
||||
[markdownlint]: https://github.com/DavidAnson/markdownlint
|
||||
|
||||
@@ -45,4 +45,4 @@ If the V8 context crashes, the DevTools will display this message.
|
||||
|
||||
Chromium logs can be enabled via the `ELECTRON_ENABLE_LOGGING` environment variable. For more information, see the [environment variables documentation](../api/environment-variables.md#electron_enable_logging).
|
||||
|
||||
Alternatively, the command line argument `--enable-logging` can be passed. More information is available in the [command line switches documentation](../api/command-line-switches.md#--enable-logging).
|
||||
Alternatively, the command line argument `--enable-logging` can be passed. More information is available in the [command line switches documentation](../api/command-line-switches.md#--enable-loggingfile).
|
||||
|
||||
@@ -18,7 +18,7 @@ distributable Electron application, such as bundling your application,
|
||||
rebranding the executable, and setting the right icons.
|
||||
|
||||
You can check the example of how to package your app with `electron-forge` in
|
||||
our [Quick Start Guide](quick-start.md#package-and-distribute-the-application).
|
||||
the [Quick Start guide](quick-start.md#package-and-distribute-your-application).
|
||||
|
||||
## Manual distribution
|
||||
|
||||
|
||||
@@ -47,18 +47,18 @@ of this theming, due to the use of the macOS 10.14 SDK.
|
||||
|
||||
## Example
|
||||
|
||||
We'll start with a working application from the
|
||||
[Quick Start Guide](quick-start.md) and add functionality gradually.
|
||||
This example demonstrates an Electron application that derives its theme colors from the
|
||||
`nativeTheme`. Additionally, it provides theme toggle and reset controls using IPC channels.
|
||||
|
||||
First, let's edit our interface so users can toggle between light and dark
|
||||
modes. This basic UI contains buttons to change the `nativeTheme.themeSource`
|
||||
setting and a text element indicating which `themeSource` value is selected.
|
||||
By default, Electron follows the system's dark mode preference, so we
|
||||
will hardcode the theme source as "System".
|
||||
```javascript fiddle='docs/fiddles/features/macos-dark-mode'
|
||||
|
||||
Add the following lines to the `index.html` file:
|
||||
```
|
||||
|
||||
```html
|
||||
### How does this work?
|
||||
|
||||
Starting with the `index.html` file:
|
||||
|
||||
```html title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
@@ -80,65 +80,70 @@ Add the following lines to the `index.html` file:
|
||||
</html>
|
||||
```
|
||||
|
||||
Next, add [event listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
|
||||
that listen for `click` events on the toggle buttons. Because the `nativeTheme`
|
||||
module only exposed in the Main process, you need to set up each listener's
|
||||
callback to use IPC to send messages to and handle responses from the Main
|
||||
process:
|
||||
And the `styles.css` file:
|
||||
|
||||
* when the "Toggle Dark Mode" button is clicked, we send the
|
||||
`dark-mode:toggle` message (event) to tell the Main process to trigger a theme
|
||||
change, and update the "Current Theme Source" label in the UI based on the
|
||||
response from the Main process.
|
||||
* when the "Reset to System Theme" button is clicked, we send the
|
||||
`dark-mode:system` message (event) to tell the Main process to use the system
|
||||
color scheme, and update the "Current Theme Source" label to `System`.
|
||||
```css title='styles.css'
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body { background: #333; color: white; }
|
||||
}
|
||||
|
||||
To add listeners and handlers, add the following lines to the `renderer.js` file:
|
||||
@media (prefers-color-scheme: light) {
|
||||
body { background: #ddd; color: black; }
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
const { ipcRenderer } = require('electron')
|
||||
The example renders an HTML page with a couple elements. The `<strong id="theme-source">`
|
||||
element shows which theme is currently selected, and the two `<button>` elements are the
|
||||
controls. The CSS file uses the [`prefers-color-scheme`][prefers-color-scheme] media query
|
||||
to set the `<body>` element background and text colors.
|
||||
|
||||
The `preload.js` script adds a new API to the `window` object called `darkMode`. This API
|
||||
exposes two IPC channels to the renderer process, `'dark-mode:toggle'` and `'dark-mode:system'`.
|
||||
It also assigns two methods, `toggle` and `system`, which pass messages from the renderer to the
|
||||
main process.
|
||||
|
||||
```js title='preload.js'
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('darkMode', {
|
||||
toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
|
||||
system: () => ipcRenderer.invoke('dark-mode:system')
|
||||
})
|
||||
```
|
||||
|
||||
Now the renderer process can communicate with the main process securely and perform the necessary
|
||||
mutations to the `nativeTheme` object.
|
||||
|
||||
The `renderer.js` file is responsible for controlling the `<button>` functionality.
|
||||
|
||||
```js title='renderer.js'
|
||||
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
|
||||
const isDarkMode = await ipcRenderer.invoke('dark-mode:toggle')
|
||||
const isDarkMode = await window.darkMode.toggle()
|
||||
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
|
||||
})
|
||||
|
||||
document.getElementById('reset-to-system').addEventListener('click', async () => {
|
||||
await ipcRenderer.invoke('dark-mode:system')
|
||||
await window.darkMode.system()
|
||||
document.getElementById('theme-source').innerHTML = 'System'
|
||||
})
|
||||
```
|
||||
|
||||
If you run your code at this point, you'll see that your buttons don't do
|
||||
anything just yet, and your Main process will output an error like this when
|
||||
you click on your buttons:
|
||||
`Error occurred in handler for 'dark-mode:toggle': No handler registered for 'dark-mode:toggle'`
|
||||
This is expected — we haven't actually touched any `nativeTheme` code yet.
|
||||
Using `addEventListener`, the `renderer.js` file adds `'click'` [event listeners][event-listeners]
|
||||
to each button element. Each event listener handler makes calls to the respective `window.darkMode`
|
||||
API methods.
|
||||
|
||||
Now that we're done wiring the IPC from the Renderer's side, the next step
|
||||
is to update the `main.js` file to handle events from the Renderer process.
|
||||
Finally, the `main.js` file represents the main process and contains the actual `nativeTheme` API.
|
||||
|
||||
Depending on the received event, we update the
|
||||
[`nativeTheme.themeSource`](../api/native-theme.md#nativethemethemesource)
|
||||
property to apply the desired theme on the system's native UI elements
|
||||
(e.g. context menus) and propagate the preferred color scheme to the Renderer
|
||||
process:
|
||||
|
||||
* Upon receiving `dark-mode:toggle`, we check if the dark theme is currently
|
||||
active using the `nativeTheme.shouldUseDarkColors` property, and set the
|
||||
`themeSource` to the opposite theme.
|
||||
* Upon receiving `dark-mode:system`, we reset the `themeSource` to `system`.
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -158,40 +163,37 @@ function createWindow () {
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The final step is to add a bit of styling to enable dark mode for the web parts
|
||||
of the UI by leveraging the [`prefers-color-scheme`][prefer-color-scheme] CSS
|
||||
attribute. The value of `prefers-color-scheme` will follow your
|
||||
`nativeTheme.themeSource` setting.
|
||||
The `ipcMain.handle` methods are how the main process responds to the click events from the buttons
|
||||
on the HTML page.
|
||||
|
||||
Create a `styles.css` file and add the following lines:
|
||||
The `'dark-mode:toggle'` IPC channel handler method checks the `shouldUseDarkColors` boolean property,
|
||||
sets the corresponding `themeSource`, and then returns the current `shouldUseDarkColors` property.
|
||||
Looking back on the renderer process event listener for this IPC channel, the return value from this
|
||||
handler is utilized to assign the correct text to the `<strong id='theme-source'>` element.
|
||||
|
||||
```css fiddle='docs/fiddles/features/macos-dark-mode'
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body { background: #333; color: white; }
|
||||
}
|
||||
The `'dark-mode:system'` IPC channel handler method assigns the string `'system'` to the `themeSource`
|
||||
and returns nothing. This also corresponds with the relative renderer process event listener as the
|
||||
method is awaited with no return value expected.
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
body { background: #ddd; color: black; }
|
||||
}
|
||||
```
|
||||
|
||||
After launching the Electron application, you can change modes or reset the
|
||||
theme to system default by clicking corresponding buttons:
|
||||
Run the example using Electron Fiddle and then click the "Toggle Dark Mode" button; the app should
|
||||
start alternating between a light and dark background color.
|
||||
|
||||

|
||||
|
||||
@@ -199,4 +201,5 @@ theme to system default by clicking corresponding buttons:
|
||||
[electron-forge]: https://www.electronforge.io/
|
||||
[electron-packager]: https://github.com/electron/electron-packager
|
||||
[packager-darwindarkmode-api]: https://electron.github.io/electron-packager/master/interfaces/electronpackager.options.html#darwindarkmodesupport
|
||||
[prefer-color-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
|
||||
[prefers-color-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
|
||||
[event-listeners]: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
# Electron Release Timelines
|
||||
|
||||
Special notes:
|
||||
|
||||
* The `-beta.1` and `stable` dates are our solid release dates.
|
||||
* We strive for weekly beta releases, however we often release more betas than scheduled.
|
||||
* All dates are our goals but there may be reasons for adjusting the stable deadline, such as security bugs.
|
||||
* Take a look at the [5.0.0 Timeline blog post](https://electronjs.org/blog/electron-5-0-timeline) for info about publicizing our release dates.
|
||||
* Since Electron 6.0, we've been targeting every other Chromium version and releasing our stable on the same day as Chrome stable. You can reference Chromium's release schedule [here](https://chromiumdash.appspot.com/schedule). See [Electron's new release cadence blog post](https://www.electronjs.org/blog/12-week-cadence) for more details on our release schedule.
|
||||
* Electron 15.0 only will include a special Alpha release. Starting in Electron 16.0, we will release on an 8-week cadence. See [Electron's new 8-week cadence blog post](https://www.electronjs.org/blog/8-week-cadence) for more details.
|
||||
|
||||
| Version | -beta.1 | Stable | Chrome | Node |
|
||||
| ------- | ------- | ------ | ------ | ---- |
|
||||
| 2.0.0 | 2018-02-21 | 2018-05-01 | M61 | v8.9 |
|
||||
| 3.0.0 | 2018-06-21 | 2018-09-18 | M66 | v10.2 |
|
||||
| 4.0.0 | 2018-10-11 | 2018-12-20 | M69 | v10.11 |
|
||||
| 5.0.0 | 2019-01-22 | 2019-04-24 | M73 | v12.0 |
|
||||
| 6.0.0 | 2019-05-01 | 2019-07-30 | M76 | v12.4 |
|
||||
| 7.0.0 | 2019-08-01 | 2019-10-22 | M78 | v12.8 |
|
||||
| 8.0.0 | 2019-10-24 | 2020-02-04 | M80 | v12.13 |
|
||||
| 9.0.0 | 2020-02-06 | 2020-05-19 | M83 | v12.14 |
|
||||
| 10.0.0 | 2020-05-21 | 2020-08-25 | M85 | v12.16 |
|
||||
| 11.0.0 | 2020-08-27 | 2020-11-17 | M87 | v12.18 |
|
||||
| 12.0.0 | 2020-11-19 | 2021-03-02 | M89 | v14.16 |
|
||||
| 13.0.0 | 2021-03-04 | 2021-05-25 | M91 | v14.x |
|
||||
| Electron | Alpha | Beta | Stable | Chrome | Node |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- |
|
||||
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | M61 | v8.9 |
|
||||
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | M66 | v10.2 |
|
||||
| 4.0.0 | -- | 2018-Oct-11 | 2018-Dec-20 | M69 | v10.11 |
|
||||
| 5.0.0 | -- | 2019-Jan-22 | 2019-Apr-24 | M73 | v12.0 |
|
||||
| 6.0.0 | -- | 2019-May-01 | 2019-Jul-30 | M76 | v12.4 |
|
||||
| 7.0.0 | -- | 2019-Aug-01 | 2019-Oct-22 | M78 | v12.8 |
|
||||
| 8.0.0 | -- | 2019-Oct-24 | 2020-Feb-04 | M80 | v12.13 |
|
||||
| 9.0.0 | -- | 2020-Feb-06 | 2020-May-19 | M83 | v12.14 |
|
||||
| 10.0.0 | -- | 2020-May-21 | 2020-Aug-25 | M85 | v12.16 |
|
||||
| 11.0.0 | -- | 2020-Aug-27 | 2020-Nov-17 | M87 | v12.18 |
|
||||
| 12.0.0 | -- | 2020-Nov-19 | 2021-Mar-02 | M89 | v14.16 |
|
||||
| 13.0.0 | -- | 2021-Mar-04 | 2021-May-25 | M91 | v14.16 |
|
||||
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | M93 | TBD |
|
||||
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | M94 | TBD |
|
||||
|
||||
@@ -51,4 +51,4 @@ Somewhere in the Electron binary there will be a sequence of bytes that look lik
|
||||
|
||||
To flip a fuse you find its position in the fuse wire and change it to "0" or "1" depending on the state you'd like.
|
||||
|
||||
You can view the current schema [here](https://github.com/electron/electron/blob/master/build/fuses/fuses.json).
|
||||
You can view the current schema [here](https://github.com/electron/electron/blob/master/build/fuses/fuses.json5).
|
||||
|
||||
@@ -11,14 +11,19 @@ npm install electron --save-dev
|
||||
See the [Electron versioning doc][versioning] for info on how to
|
||||
manage Electron versions in your apps.
|
||||
|
||||
## Global Installation
|
||||
## Running Electron ad-hoc
|
||||
|
||||
You can also install the `electron` command globally in your `$PATH`:
|
||||
If you're in a pinch and would prefer to not use `npm install` in your local
|
||||
project, you can also run Electron ad-hoc using the [`npx`][npx] command runner
|
||||
bundled with `npm`:
|
||||
|
||||
```sh
|
||||
npm install electron -g
|
||||
npx electron .
|
||||
```
|
||||
|
||||
The above command will run the current working directory with Electron. Note that
|
||||
any dependencies in your app will not be installed.
|
||||
|
||||
## Customization
|
||||
|
||||
If you want to change the architecture that is downloaded (e.g., `ia32` on an
|
||||
@@ -130,14 +135,18 @@ a text file. A typical cache might look like this:
|
||||
|
||||
## Skip binary download
|
||||
|
||||
When installing the `electron` NPM package, it automatically downloads the electron binary.
|
||||
Under the hood, Electron's JavaScript API binds to a binary that contains its
|
||||
implementations. Because this binary is crucial to the function of any Electron app,
|
||||
it is downloaded by default in the `postinstall` step every time you install `electron`
|
||||
from the npm registry.
|
||||
|
||||
This can sometimes be unnecessary, e.g. in a CI environment, when testing another component.
|
||||
However, if you want to install your project's dependencies but don't need to use
|
||||
Electron functionality, you can set the `ELECTRON_SKIP_BINARY_DOWNLOAD` environment
|
||||
variable to prevent the binary from being downloaded. For instance, this feature can
|
||||
be useful in continuous integration environments when running unit tests that mock
|
||||
out the `electron` module.
|
||||
|
||||
To prevent the binary from being downloaded when you install all npm dependencies you can set the environment variable `ELECTRON_SKIP_BINARY_DOWNLOAD`.
|
||||
E.g.:
|
||||
|
||||
```sh
|
||||
```sh npm2yarn
|
||||
ELECTRON_SKIP_BINARY_DOWNLOAD=1 npm install
|
||||
```
|
||||
|
||||
@@ -178,6 +187,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
|
||||
[npx]: https://docs.npmjs.com/cli/v7/commands/npx
|
||||
[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
|
||||
|
||||
59
docs/tutorial/introduction.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Introduction
|
||||
|
||||
Welcome to the Electron documentation! If this is your first time developing
|
||||
an Electron app, read through this Getting Started section to get familiar with the
|
||||
basics. Otherwise, feel free to explore our guides and API documentation!
|
||||
|
||||
## What is Electron?
|
||||
|
||||
Electron is a framework for building desktop applications using JavaScript,
|
||||
HTML, and CSS. By embedding [Chromium][chromium] and [Node.js][node] into its
|
||||
binary, Electron allows you to maintain one JavaScript codebase and create
|
||||
cross-platform apps that work on Windows, macOS, and Linux — no native development
|
||||
experience required.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
These docs operate under the assumption that the reader is familiar with both
|
||||
Node.js and general web development. If you need to get more comfortable with
|
||||
either of these areas, we recommend the following resources:
|
||||
|
||||
* [Getting started with the Web (MDN)][mdn-guide]
|
||||
* [Introduction to Node.js][node-guide]
|
||||
|
||||
Moreover, you'll have a better time understanding how Electron works if you get
|
||||
acquainted with Chromium's process model. You can get a brief overview of
|
||||
Chrome architecture with the [Chrome comic][comic], which was released alongside
|
||||
Chrome's launch back in 2008. Although it's been over a decade since then, the
|
||||
core principles introduced in the comic remain helpful to understand Electron.
|
||||
|
||||
## Running examples with Electron Fiddle
|
||||
|
||||
[Electron Fiddle][fiddle] is a sandbox app written with Electron and supported by
|
||||
Electron's maintainers. We highly recommend installing it as a learning tool to
|
||||
experiment with Electron's APIs or to prototype features during development.
|
||||
|
||||
Fiddle also integrates nicely with our documentation. When browsing through examples
|
||||
in our tutorials, you'll frequently see an "Open in Electron Fiddle" button underneath
|
||||
a code block. If you have Fiddle installed, this button will open a
|
||||
`fiddle.electronjs.org` link that will automatically load the example into Fiddle,
|
||||
no copy-pasting required.
|
||||
|
||||
## Getting help
|
||||
|
||||
Are you getting stuck anywhere? Here are a few links to places to look:
|
||||
|
||||
* If you need help with developing your app, our [community Discord server][discord]
|
||||
is a great place to get advice from other Electron app developers.
|
||||
* If you suspect you're running into a bug with the `electron` package, please check
|
||||
the [GitHub issue tracker][issue-tracker] to see if any existing issues match your
|
||||
problem. If not, feel free to fill out our bug report template and submit a new issue.
|
||||
|
||||
[chromium]: https://www.chromium.org/
|
||||
[node]: https://nodejs.org/
|
||||
[mdn-guide]: https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web
|
||||
[node-guide]: https://nodejs.dev/learn
|
||||
[comic]: https://www.google.com/googlebooks/chrome/
|
||||
[fiddle]: https://electronjs.org/fiddle
|
||||
[issue-tracker]: https://github.com/electron/electron/issues
|
||||
[discord]: https://discord.gg/electron
|
||||
@@ -81,11 +81,17 @@ If you want to handle keyboard shortcuts within a [BrowserWindow], you can
|
||||
listen for the `keyup` and `keydown` [DOM events][dom-events] inside the
|
||||
renderer process using the [addEventListener() API][addEventListener-api].
|
||||
|
||||
```js
|
||||
window.addEventListener('keyup', doSomething, true)
|
||||
```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/web-apis|focus=renderer.js'
|
||||
function handleKeyPress(event) {
|
||||
// You can put code here to handle the keypress.
|
||||
document.getElementById("last-keypress").innerText = event.key;
|
||||
console.log(`You pressed ${event.key}`);
|
||||
}
|
||||
|
||||
window.addEventListener('keyup', handleKeyPress, true);
|
||||
```
|
||||
|
||||
Note the third parameter `true` indicates that the listener will always receive
|
||||
> Note: the third parameter `true` indicates that the listener will always receive
|
||||
key presses before other listeners so they can't have `stopPropagation()`
|
||||
called on them.
|
||||
|
||||
@@ -95,8 +101,6 @@ The [`before-input-event`](../api/web-contents.md#event-before-input-event) even
|
||||
is emitted before dispatching `keydown` and `keyup` events in the page. It can
|
||||
be used to catch and handle custom shortcuts that are not visible in the menu.
|
||||
|
||||
##### Example
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the
|
||||
following lines:
|
||||
@@ -105,7 +109,7 @@ following lines:
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } })
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
|
||||
win.loadFile('index.html')
|
||||
win.webContents.on('before-input-event', (event, input) => {
|
||||
|
||||