Compare commits

..

7 Commits

Author SHA1 Message Date
Electron Bot
95e3853b77 Bump v10.0.0-beta.1 2020-05-21 14:28:15 -07:00
Samuel Attard
9de5ede1fb Revert "feat: look harder for a commit's pull request. (#23593)"
This reverts commit 2342aaffbd.
2020-05-21 14:27:04 -07:00
Electron Bot
05efbbcdd5 Revert "Bump v10.0.0-beta.1"
This reverts commit 2789f32efb.
2020-05-21 14:23:22 -07:00
Electron Bot
2789f32efb Bump v10.0.0-beta.1 2020-05-21 14:23:00 -07:00
Samuel Attard
4c8b884998 fix: support 10-x-y in the release notes generator (#23709) 2020-05-21 14:13:17 -07:00
Electron Bot
03ddd2d7af Revert "Bump v10.0.0-beta.1"
This reverts commit c141b1a906.
2020-05-21 13:33:35 -07:00
Electron Bot
c141b1a906 Bump v10.0.0-beta.1 2020-05-21 13:33:02 -07:00
914 changed files with 18112 additions and 32218 deletions

View File

@@ -37,18 +37,10 @@ parameters:
type: boolean
default: false
run-osx-publish-arm64:
type: boolean
default: false
run-mas-publish:
type: boolean
default: false
run-mas-publish-arm64:
type: boolean
default: false
run-linux-publish:
type: boolean
default: false
@@ -85,17 +77,12 @@ machine-linux-2xlarge: &machine-linux-2xlarge
machine-mac: &machine-mac
macos:
xcode: "12.2.0"
xcode: "11.1.0"
machine-mac-large: &machine-mac-large
resource_class: large
macos:
xcode: "12.2.0"
machine-mac-large-arm: &machine-mac-large-arm
resource_class: large
macos:
xcode: "12.2.0"
xcode: "11.1.0"
# Build configurations options.
env-testing-build: &env-testing-build
@@ -136,11 +123,6 @@ env-arm: &env-arm
BUILD_NATIVE_MKSNAPSHOT: 1
TARGET_ARCH: arm
env-apple-silicon: &env-apple-silicon
GN_EXTRA_ARGS: 'target_cpu = "arm64" use_prebuilt_v8_context_snapshot = true'
TARGET_ARCH: arm64
USE_PREBUILT_V8_CONTEXT_SNAPSHOT: 1
env-arm64: &env-arm64
GN_EXTRA_ARGS: 'target_cpu = "arm64" fatal_linker_warnings = false enable_linux_installer = false'
MKSNAPSHOT_TOOLCHAIN: //build/toolchain/linux:clang_arm64
@@ -151,12 +133,6 @@ env-mas: &env-mas
GN_EXTRA_ARGS: 'is_mas_build = true'
MAS_BUILD: 'true'
env-mas-apple-silicon: &env-mas-apple-silicon
GN_EXTRA_ARGS: 'target_cpu = "arm64" is_mas_build = true use_prebuilt_v8_context_snapshot = true'
MAS_BUILD: 'true'
TARGET_ARCH: arm64
USE_PREBUILT_V8_CONTEXT_SNAPSHOT: 1
# Misc build configuration options.
env-enable-sccache: &env-enable-sccache
USE_SCCACHE: true
@@ -336,81 +312,14 @@ step-get-more-space-on-mac: &step-get-more-space-on-mac
name: Free up space on MacOS
command: |
if [ "`uname`" == "Darwin" ]; then
sudo mkdir -p $TMPDIR/del-target
if [ "$TARGET_ARCH" == "arm64" ]; then
# Remount the root volume as writable, don't ask questions plz
sudo mount -uw /
fi
tmpify() {
if [ -d "$1" ]; then
sudo mv "$1" $TMPDIR/del-target/$(echo $1|shasum -a 256|head -n1|cut -d " " -f1)
fi
}
strip_arm_deep() {
opwd=$(pwd)
cd $1
f=$(find . -perm +111 -type f)
for fp in $f
do
if [[ $(file "$fp") == *"universal binary"* ]]; then
if [[ $(file "$fp") == *"arm64e)"* ]]; then
sudo lipo -remove arm64e "$fp" -o "$fp" || true
fi
if [[ $(file "$fp") == *"arm64)"* ]]; then
sudo lipo -remove arm64 "$fp" -o "$fp" || true
fi
fi
done
cd $opwd
}
tmpify /Library/Developer/CoreSimulator
tmpify ~/Library/Developer/CoreSimulator
tmpify $(xcode-select -p)/Platforms/AppleTVOS.platform
tmpify $(xcode-select -p)/Platforms/iPhoneOS.platform
tmpify $(xcode-select -p)/Platforms/WatchOS.platform
tmpify $(xcode-select -p)/Platforms/WatchSimulator.platform
tmpify $(xcode-select -p)/Platforms/AppleTVSimulator.platform
tmpify $(xcode-select -p)/Platforms/iPhoneSimulator.platform
tmpify $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/metal/ios
tmpify $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift
tmpify $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0
tmpify ~/.rubies
tmpify ~/Library/Caches/Homebrew
tmpify /usr/local/Homebrew
sudo rm -rf $TMPDIR/del-target
if [ "$TARGET_ARCH" == "arm64" ]; then
sudo rm -rf "/System/Library/Desktop Pictures"
sudo rm -rf /System/Library/Templates/Data
sudo rm -rf /System/Library/Speech/Voices
sudo rm -rf "/System/Library/Screen Savers"
sudo rm -rf /System/Volumes/Data/Library/Developer/CommandLineTools/SDKs
sudo rm -rf "/System/Volumes/Data/Library/Application Support/Apple/Photos/Print Products"
sudo rm -rf /System/Volumes/Data/Library/Java
sudo rm -rf /System/Volumes/Data/Library/Ruby
sudo rm -rf /System/Volumes/Data/Library/Printers
sudo rm -rf /System/iOSSupport
sudo rm -rf /System/Applications/*.app
sudo rm -rf /System/Applications/Utilities/*.app
sudo rm -rf /System/Library/LinguisticData
sudo rm -rf /System/Volumes/Data/private/var/db/dyld/*
# sudo rm -rf /System/Library/Fonts/*
# sudo rm -rf /System/Library/PreferencePanes
sudo rm -rf /System/Library/AssetsV2/*
sudo rm -rf /Applications/Safari.app
sudo rm -rf ~/project/src/build/linux
sudo rm -rf ~/project/src/third_party/catapult/tracing/test_data
sudo rm -rf ~/project/src/third_party/angle/third_party/VK-GL-CTS
# lipo off some huge binaries arm64 versions to save space
strip_arm_deep $(xcode-select -p)/../SharedFrameworks
strip_arm_deep /System/Volumes/Data/Library/Developer/CommandLineTools/usr
fi
sudo rm -rf /Library/Developer/CoreSimulator
sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform
sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform
sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform
sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform
sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform
fi
background: true
# On macOS delete all .git directories under src/ expect for
# third_party/angle/ because of build time generation of file
@@ -508,29 +417,7 @@ step-electron-build: &step-electron-build
rm -f src/out/Default/libffmpeg.so
fi
cd src
# Enable if things get really bad
# if [ "$TARGET_ARCH" == "arm64" ] &&[ "`uname`" == "Darwin" ]; then
# diskutil erasevolume HFS+ "xcode_disk" `hdiutil attach -nomount ram://12582912`
# mv /Applications/Xcode-12.beta.5.app /Volumes/xcode_disk/
# ln -s /Volumes/xcode_disk/Xcode-12.beta.5.app /Applications/Xcode-12.beta.5.app
# fi
# Lets generate a snapshot and mksnapshot and then delete all the x-compiled generated files to save space
if [ "$USE_PREBUILT_V8_CONTEXT_SNAPSHOT" == "1" ]; then
ninja -C out/Default electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
ninja -C out/Default tools/v8_context_snapshot -j $NUMBER_OF_NINJA_PROCESSES
gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
rm -rf out/Default/clang_x64_v8_arm64/obj
# Regenerate because we just deleted some ninja files
if [ "$USE_GOMA" == "true" ]; then
gn gen out/Default --args="import(\"$GN_CONFIG\") import(\"$GN_GOMA_FILE\") $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
else
gn gen out/Default --args="import(\"$GN_CONFIG\") cc_wrapper=\"$SCCACHE_PATH\" $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
fi
fi
ninja -C out/Default electron -j $NUMBER_OF_NINJA_PROCESSES
node electron/script/check-symlinks.js
step-native-unittests-build: &step-native-unittests-build
run:
@@ -778,10 +665,8 @@ step-mksnapshot-build: &step-mksnapshot-build
name: mksnapshot build
command: |
cd src
if [ "$USE_PREBUILT_V8_CONTEXT_SNAPSHOT" != "1" ]; then
ninja -C out/Default electron:electron_mksnapshot -j $NUMBER_OF_NINJA_PROCESSES
gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
fi
ninja -C out/Default electron:electron_mksnapshot -j $NUMBER_OF_NINJA_PROCESSES
gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
if [ "`uname`" != "Darwin" ]; then
if [ "$TARGET_ARCH" == "arm" ]; then
electron/script/strip-binaries.py --file $PWD/out/Default/clang_x86_v8_arm/mksnapshot
@@ -794,7 +679,7 @@ step-mksnapshot-build: &step-mksnapshot-build
electron/script/strip-binaries.py --file $PWD/out/Default/v8_context_snapshot_generator
fi
fi
if [ "$USE_PREBUILT_V8_CONTEXT_SNAPSHOT" != "1" ] && [ "$SKIP_DIST_ZIP" != "1" ]; then
if [ "$SKIP_DIST_ZIP" != "1" ]; then
ninja -C out/Default electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
(cd out/Default; zip mksnapshot.zip mksnapshot_args gen/v8/embedded.S)
fi
@@ -821,11 +706,12 @@ step-hunspell-store: &step-hunspell-store
step-maybe-generate-breakpad-symbols: &step-maybe-generate-breakpad-symbols
run:
name: Generate breakpad symbols
no_output_timeout: 30m
command: |
if [ "$GENERATE_SYMBOLS" == "true" ]; then
cd src
ninja -C out/Default electron:electron_symbols
cd out/Default/breakpad_symbols
find . -name \*.sym -print0 | xargs -0 npx @sentry/cli@1.51.1 difutil bundle-sources
fi
step-maybe-zip-symbols: &step-maybe-zip-symbols
@@ -854,13 +740,9 @@ step-maybe-cross-arch-snapshot: &step-maybe-cross-arch-snapshot
elif [ "$TARGET_ARCH" == "arm64" ]; then
export MKSNAPSHOT_PATH="clang_x64_v8_arm64"
fi
cp "out/Default/$MKSNAPSHOT_PATH/mksnapshot" out/Default
cp "out/Default/$MKSNAPSHOT_PATH/mksnapshot" out/Default
cp "out/Default/$MKSNAPSHOT_PATH/libffmpeg.so" out/Default
cp "out/Default/$MKSNAPSHOT_PATH/v8_context_snapshot_generator" out/Default
if [ "`uname`" == "Linux" ]; then
cp "out/Default/$MKSNAPSHOT_PATH/libffmpeg.so" out/Default
elif [ "`uname`" == "Darwin" ]; then
cp "out/Default/$MKSNAPSHOT_PATH/libffmpeg.dylib" out/Default
fi
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --create-snapshot-only
mkdir cross-arch-snapshots
cp out/Default-mksnapshot-test/*.bin cross-arch-snapshots
@@ -879,13 +761,8 @@ step-maybe-trigger-arm-test: &step-maybe-trigger-arm-test
# Only run for non-fork prs
if [ "$TRIGGER_ARM_TEST" == "true" ] && [ -z "$CIRCLE_PR_NUMBER" ]; then
#Trigger VSTS job, passing along CircleCI job number and branch to build
if [ "`uname`" == "Darwin" ]; then
echo "Triggering electron-arm2-testing build on Azure DevOps"
node electron/script/release/ci-release-build.js --job=electron-arm2-testing --ci=DevOps --armTest --circleBuildNum=$CIRCLE_BUILD_NUM $CIRCLE_BRANCH
else
echo "Triggering electron-$TARGET_ARCH-testing build on VSTS"
node electron/script/release/ci-release-build.js --job=electron-$TARGET_ARCH-testing --ci=VSTS --armTest --circleBuildNum=$CIRCLE_BUILD_NUM $CIRCLE_BRANCH
fi
echo "Triggering electron-$TARGET_ARCH-testing build on VSTS"
node electron/script/release/ci-release-build.js --job=electron-$TARGET_ARCH-testing --ci=VSTS --armTest --circleBuildNum=$CIRCLE_BUILD_NUM $CIRCLE_BRANCH
fi
step-maybe-generate-typescript-defs: &step-maybe-generate-typescript-defs
@@ -933,13 +810,8 @@ step-touch-sync-done: &step-touch-sync-done
step-maybe-restore-src-cache: &step-maybe-restore-src-cache
restore_cache:
keys:
- v8-src-cache-{{ checksum "src/electron/.depshash" }}
- v7-src-cache-{{ checksum "src/electron/.depshash" }}
name: Restoring src cache
step-maybe-restore-src-cache-marker: &step-maybe-restore-src-cache-marker
restore_cache:
keys:
- v1-src-cache-marker-{{ checksum "src/electron/.depshash" }}
name: Restoring src cache marker
# Restore exact or closest git cache based on the hash of DEPS and .circle-sync-done
# If the src cache was restored above then this will match an empty cache
@@ -958,7 +830,7 @@ step-restore-out-cache: &step-restore-out-cache
paths:
- ./src/out/Default
keys:
- v9-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
- v7-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
name: Restoring out cache
step-set-git-cache-path: &step-set-git-cache-path
@@ -982,7 +854,7 @@ step-save-out-cache: &step-save-out-cache
save_cache:
paths:
- ./src/out/Default
key: v9-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
key: v7-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
name: Persisting out cache
step-run-electron-only-hooks: &step-run-electron-only-hooks
@@ -1011,26 +883,14 @@ step-minimize-workspace-size-from-checkout: &step-minimize-workspace-size-from-c
rm -rf src/third_party/blink/web_tests
rm -rf src/third_party/blink/perf_tests
rm -rf src/third_party/WebKit/LayoutTests
rm -rf third_party/electron_node/deps/openssl
rm -rf third_party/electron_node/deps/v8
rm -rf chrome/test/data/xr/webvr_info
# Save the src cache based on the deps hash
step-save-src-cache: &step-save-src-cache
save_cache:
paths:
- /var/portal
key: v8-src-cache-{{ checksum "/var/portal/src/electron/.depshash" }}
- /portal
key: v7-src-cache-{{ checksum "/portal/src/electron/.depshash" }}
name: Persisting src cache
step-make-src-cache-marker: &step-make-src-cache-marker
run:
name: Making src cache marker
command: touch .src-cache-marker
step-save-src-cache-marker: &step-save-src-cache-marker
save_cache:
paths:
- .src-cache-marker
key: v1-src-cache-marker-{{ checksum "/var/portal/src/electron/.depshash" }}
# Check for doc only change
step-check-for-doc-only-change: &step-check-for-doc-only-change
@@ -1121,11 +981,6 @@ steps-lint: &steps-lint
cd src/electron
node script/yarn install --frozen-lockfile
node script/yarn lint
- run:
name: Run Script Typechecker
command: |
cd src/electron
node script/yarn tsc -p tsconfig.script.json
steps-checkout-and-save-cache: &steps-checkout-and-save-cache
steps:
@@ -1141,8 +996,7 @@ steps-checkout-and-save-cache: &steps-checkout-and-save-cache
- *step-generate-deps-hash
- *step-touch-sync-done
- maybe-restore-portaled-src-cache:
halt-if-successful: true
- maybe-restore-portaled-src-cache
- *step-maybe-restore-git-cache
- *step-set-git-cache-path
# This sync call only runs if .circle-sync-done is an EMPTY file
@@ -1163,12 +1017,10 @@ steps-checkout-and-save-cache: &steps-checkout-and-save-cache
- run:
name: Move src folder to the cross-OS portal
command: |
sudo mkdir -p /var/portal
sudo chown -R $(id -u):$(id -g) /var/portal
mv ./src /var/portal
sudo mkdir -p /portal
sudo chown -R $(id -u):$(id -g) /portal
mv ./src /portal
- *step-save-src-cache
- *step-make-src-cache-marker
- *step-save-src-cache-marker
steps-electron-gn-check: &steps-electron-gn-check
steps:
@@ -1189,8 +1041,8 @@ steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-cha
- *step-depot-tools-get
- *step-depot-tools-add-to-path
- *step-restore-brew-cache
- *step-install-gnutar-on-mac
- *step-get-more-space-on-mac
- *step-install-gnutar-on-mac
- *step-generate-deps-hash
- *step-touch-sync-done
- maybe-restore-portaled-src-cache
@@ -1372,34 +1224,20 @@ chromium-upgrade-branches: &chromium-upgrade-branches
# Command Aliases
commands:
maybe-restore-portaled-src-cache:
parameters:
halt-if-successful:
type: boolean
default: false
steps:
- run:
name: Prepare for cross-OS sync restore
command: |
sudo mkdir -p /var/portal
sudo chown -R $(id -u):$(id -g) /var/portal
- when:
condition: << parameters.halt-if-successful >>
steps:
- *step-maybe-restore-src-cache-marker
- run:
name: Halt the job early if the src cache exists
command: |
if [ -f ".src-cache-marker" ]; then
circleci-agent step halt
fi
sudo mkdir -p /portal
sudo chown -R $(id -u):$(id -g) /portal
- *step-maybe-restore-src-cache
- run:
name: Fix the src cache restore point on macOS
command: |
if [ -d "/var/portal/src" ]; then
if [ -d "/portal/src" ]; then
echo Relocating Cache
rm -rf src
mv /var/portal/src ./
mv /portal/src ./
fi
checkout-from-cache:
steps:
@@ -1862,7 +1700,7 @@ jobs:
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
- electron-publish:
attach: false
checkout: true
@@ -1874,7 +1712,7 @@ jobs:
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
- electron-publish:
attach: true
checkout: false
@@ -1926,7 +1764,7 @@ jobs:
<<: *env-32bit-release
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
- electron-publish:
attach: false
checkout: true
@@ -1940,12 +1778,12 @@ jobs:
<<: *env-32bit-release
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
- electron-publish:
attach: true
checkout: false
linux-arm-testing:
<<: *machine-linux-2xlarge
<<: *machine-linux-xlarge
environment:
<<: *env-global
<<: *env-arm
@@ -1993,7 +1831,7 @@ jobs:
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
- electron-publish:
attach: false
checkout: true
@@ -2007,12 +1845,12 @@ jobs:
<<: *env-32bit-release
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
- electron-publish:
attach: true
checkout: false
linux-arm64-testing:
<<: *machine-linux-2xlarge
<<: *machine-linux-xlarge
environment:
<<: *env-global
<<: *env-arm64
@@ -2067,7 +1905,7 @@ jobs:
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm64=True --custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
- electron-publish:
attach: false
checkout: true
@@ -2080,11 +1918,11 @@ jobs:
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
- electron-publish:
attach: true
checkout: false
osx-testing-x64:
osx-testing:
<<: *machine-mac-large
environment:
<<: *env-mac-large
@@ -2099,14 +1937,22 @@ jobs:
checkout-and-assume-cache: true
attach: false
osx-testing-x64-gn-check:
osx-testing-gn-check:
<<: *machine-mac
environment:
<<: *env-machine-mac
<<: *env-testing-build
<<: *steps-electron-gn-check
osx-release-x64:
osx-chromedriver:
<<: *machine-mac
environment:
<<: *env-machine-mac
<<: *env-release-build
<<: *env-send-slack-notifications
<<: *steps-chromedriver-build
osx-release:
<<: *machine-mac-large
environment:
<<: *env-mac-large
@@ -2120,7 +1966,7 @@ jobs:
checkout-and-assume-cache: true
attach: false
osx-publish-x64:
osx-publish:
<<: *machine-mac-large
environment:
<<: *env-mac-large-release
@@ -2129,25 +1975,11 @@ jobs:
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
- electron-publish:
attach: false
checkout: true
osx-publish-arm64:
<<: *machine-mac-large-arm
environment:
<<: *env-mac-large-release
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-apple-silicon
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
attach: false
checkout: true
osx-publish-x64-skip-checkout:
osx-publish-skip-checkout:
<<: *machine-mac-large
environment:
<<: *env-mac-large-release
@@ -2155,40 +1987,11 @@ jobs:
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
- electron-publish:
attach: true
checkout: false
osx-publish-arm64-skip-checkout:
<<: *machine-mac-large-arm
environment:
<<: *env-mac-large-release
<<: *env-release-build
<<: *env-enable-sccache
<<: *env-apple-silicon
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
attach: true
checkout: false
osx-testing-arm64:
<<: *machine-mac-large-arm
environment:
<<: *env-mac-large
<<: *env-testing-build
<<: *env-ninja-status
<<: *env-macos-build
<<: *env-apple-silicon
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
steps:
- electron-build:
persist: true
checkout: false
checkout-and-assume-cache: true
attach: false
mas-testing-x64:
mas-testing:
<<: *machine-mac-large
environment:
<<: *env-mac-large
@@ -2204,7 +2007,7 @@ jobs:
checkout-and-assume-cache: true
attach: false
mas-testing-x64-gn-check:
mas-testing-gn-check:
<<: *machine-mac
environment:
<<: *env-machine-mac
@@ -2237,25 +2040,11 @@ jobs:
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
- electron-publish:
attach: false
checkout: true
mas-publish-arm64:
<<: *machine-mac-large-arm
environment:
<<: *env-mac-large-release
<<: *env-mas-apple-silicon
<<: *env-release-build
<<: *env-enable-sccache
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_boto=True --custom-var=checkout_requests=True'
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
attach: false
checkout: true
mas-publish-x64-skip-checkout:
mas-publish-skip-checkout:
<<: *machine-mac-large
environment:
<<: *env-mac-large-release
@@ -2264,39 +2053,10 @@ jobs:
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
- electron-publish:
attach: true
checkout: false
mas-publish-arm64-skip-checkout:
<<: *machine-mac-large-arm
environment:
<<: *env-mac-large-release
<<: *env-mas-apple-silicon
<<: *env-release-build
<<: *env-enable-sccache
UPLOAD_TO_S3: << pipeline.parameters.upload-to-s3 >>
steps:
- electron-publish:
attach: true
checkout: false
mas-testing-arm64:
<<: *machine-mac-large-arm
environment:
<<: *env-mac-large
<<: *env-testing-build
<<: *env-ninja-status
<<: *env-macos-build
<<: *env-mas-apple-silicon
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
steps:
- electron-build:
persist: true
checkout: false
checkout-and-assume-cache: true
attach: false
# Layer 3: Tests.
linux-x64-unittests:
<<: *machine-linux-2xlarge
@@ -2420,7 +2180,7 @@ jobs:
<<: *env-send-slack-notifications
<<: *steps-verify-ffmpeg
osx-testing-x64-tests:
osx-testing-tests:
<<: *machine-mac-large
environment:
<<: *env-mac-large
@@ -2428,7 +2188,7 @@ jobs:
parallelism: 2
<<: *steps-tests
osx-release-x64-tests:
osx-release-tests:
<<: *machine-mac-large
environment:
<<: *env-mac-large
@@ -2443,7 +2203,7 @@ jobs:
<<: *env-send-slack-notifications
<<: *steps-verify-ffmpeg
mas-testing-x64-tests:
mas-testing-tests:
<<: *machine-mac-large
environment:
<<: *env-mac-large
@@ -2507,7 +2267,7 @@ jobs:
steps:
- *step-maybe-notify-slack-success
osx-release-x64-summary:
osx-release-summary:
<<: *machine-mac
environment:
<<: *env-machine-mac
@@ -2572,7 +2332,7 @@ workflows:
publish-osx:
when: << pipeline.parameters.run-osx-publish >>
jobs:
- osx-publish-x64:
- osx-publish:
context: release-env
publish-mas:
@@ -2581,32 +2341,14 @@ workflows:
- mas-publish:
context: release-env
publish-osx-arm64:
when: << pipeline.parameters.run-osx-publish-arm64 >>
jobs:
- osx-publish-arm64:
context: release-env
publish-mas-arm64:
when: << pipeline.parameters.run-mas-publish-arm64 >>
jobs:
- mas-publish-arm64:
context: release-env
publish-macos:
when: << pipeline.parameters.run-macos-publish >>
jobs:
- mac-checkout
- osx-publish-x64-skip-checkout:
- osx-publish-skip-checkout:
requires:
- mac-checkout
- mas-publish-x64-skip-checkout:
requires:
- mac-checkout
- osx-publish-arm64-skip-checkout:
requires:
- mac-checkout
- mas-publish-arm64-skip-checkout:
- mas-publish-skip-checkout:
requires:
- mac-checkout
@@ -2661,37 +2403,29 @@ workflows:
- mac-checkout-fast
- mac-checkout-and-save-cache
- osx-testing-x64:
- osx-testing:
requires:
- mac-checkout-and-save-cache
- osx-testing-x64-gn-check:
- osx-testing-gn-check:
requires:
- mac-checkout-fast
- osx-testing-x64-tests:
- osx-testing-tests:
requires:
- osx-testing-x64
- osx-testing
- osx-testing-arm64:
- mas-testing:
requires:
- mac-checkout-and-save-cache
- mas-testing-x64:
requires:
- mac-checkout-and-save-cache
- mas-testing-x64-gn-check:
- mas-testing-gn-check:
requires:
- mac-checkout-fast
- mas-testing-x64-tests:
- mas-testing-tests:
requires:
- mas-testing-x64
- mas-testing-arm64:
requires:
- mac-checkout-and-save-cache
- mas-testing
nightly-linux-release-test:
triggers:
@@ -2755,19 +2489,19 @@ workflows:
- mac-checkout-fast
- mac-checkout-and-save-cache
- osx-release-x64:
- osx-release:
requires:
- mac-checkout-and-save-cache
- osx-release-x64-tests:
- osx-release-tests:
requires:
- osx-release-x64
- osx-release
- osx-verify-ffmpeg:
requires:
- osx-release-x64
- osx-release-x64-summary:
- osx-release
- osx-release-summary:
requires:
- osx-release-x64
- osx-release-x64-tests
- osx-release
- osx-release-tests
- osx-verify-ffmpeg
- mas-release:

View File

@@ -28,12 +28,10 @@
},
"globals": {
"standardScheme": "readonly",
"globalThis": "readonly",
"BUILDFLAG": "readonly",
"ENABLE_DESKTOP_CAPTURER": "readonly",
"ENABLE_REMOTE_MODULE": "readonly",
"ENABLE_VIEWS_API": "readonly",
"BigInt": "readonly"
"ENABLE_VIEWS_API": "readonly"
},
"overrides": [
{

10
.gitattributes vendored
View File

@@ -2,13 +2,3 @@
# files to be checked out with LF endings even if core.autocrlf is true.
*.patch text eol=lf
patches/**/.patches merge=union
# Source code and markdown files should always use LF as line ending.
*.cc text eol=lf
*.mm text eol=lf
*.h text eol=lf
*.js text eol=lf
*.ts text eol=lf
*.py text eol=lf
*.ps1 text eol=lf
*.md text eol=lf

View File

@@ -15,7 +15,6 @@ Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTIN
- [ ] relevant documentation is changed or added
- [ ] PR title follows semantic [commit guidelines](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines)
- [ ] [PR release notes](https://github.com/electron/clerk/blob/master/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/master/README.md#examples).
- [ ] This is **NOT A BREAKING CHANGE**. Breaking changes may not be merged to master until 11-x-y is branched.
#### Release Notes

218
BUILD.gn
View File

@@ -49,10 +49,6 @@ if (is_linux) {
}
}
declare_args() {
use_prebuilt_v8_context_snapshot = false
}
branding = read_file("shell/app/BRANDING.json", "json")
electron_project_name = branding.project_name
electron_product_name = branding.product_name
@@ -98,15 +94,6 @@ npm_action("build_electron_definitions") {
outputs = [ "$target_gen_dir/tsc/typings/electron.d.ts" ]
}
webpack_build("electron_asar_bundle") {
deps = [ ":build_electron_definitions" ]
inputs = auto_filenames.asar_bundle_deps
config_file = "//electron/build/webpack/webpack.config.asar.js"
out_file = "$target_gen_dir/js2c/asar_bundle.js"
}
webpack_build("electron_browser_bundle") {
deps = [ ":build_electron_definitions" ]
@@ -152,18 +139,25 @@ webpack_build("electron_isolated_renderer_bundle") {
out_file = "$target_gen_dir/js2c/isolated_bundle.js"
}
copy("electron_js2c_copy") {
sources = [
"lib/common/asar.js",
"lib/common/asar_init.js",
]
outputs = [ "$target_gen_dir/js2c/{{source_file_part}}" ]
}
action("electron_js2c") {
deps = [
":electron_asar_bundle",
":electron_browser_bundle",
":electron_isolated_renderer_bundle",
":electron_js2c_copy",
":electron_renderer_bundle",
":electron_sandboxed_renderer_bundle",
":electron_worker_bundle",
]
sources = [
"$target_gen_dir/js2c/asar_bundle.js",
webpack_sources = [
"$target_gen_dir/js2c/browser_init.js",
"$target_gen_dir/js2c/isolated_bundle.js",
"$target_gen_dir/js2c/renderer_init.js",
@@ -171,10 +165,15 @@ action("electron_js2c") {
"$target_gen_dir/js2c/worker_init.js",
]
sources = webpack_sources + [
"$target_gen_dir/js2c/asar.js",
"$target_gen_dir/js2c/asar_init.js",
]
inputs = sources + [ "//third_party/electron_node/tools/js2c.py" ]
outputs = [ "$root_gen_dir/electron_natives.cc" ]
script = "build/js2c.py"
script = "tools/js2c.py"
args = [ rebase_path("//third_party/electron_node") ] +
rebase_path(outputs, root_build_dir) +
rebase_path(sources, root_build_dir)
@@ -323,10 +322,10 @@ source_set("electron_lib") {
"shell/common/api:mojo",
"//base:base_static",
"//base/allocator:buildflags",
"//chrome/app:command_ids",
"//chrome/app/resources:platform_locale_settings",
"//chrome/services/printing/public/mojom",
"//components/certificate_transparency",
"//components/crash/core/app",
"//components/language/core/browser",
"//components/net_log",
"//components/network_hints/browser",
@@ -348,7 +347,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,7 +362,6 @@ source_set("electron_lib") {
"//services/viz/privileged/mojom/compositing",
"//skia",
"//third_party/blink/public:blink",
"//third_party/blink/public:blink_devtools_inspector_resources",
"//third_party/boringssl",
"//third_party/electron_node:node_lib",
"//third_party/inspector_protocol:crdtp",
@@ -435,9 +432,6 @@ source_set("electron_lib") {
"*\bviews/*",
]
}
if (!is_mas_build) {
deps += [ "//components/crash/core/app" ]
}
set_sources_assignment_filter(
sources_assignment_filter + extra_source_filters)
@@ -463,14 +457,11 @@ source_set("electron_lib") {
deps += [
"//components/remote_cocoa/app_shim",
"//content/common:mac_helpers",
"//third_party/crashpad/crashpad/client",
"//ui/accelerated_widget_mac",
]
if (!is_mas_build) {
deps += [ "//third_party/crashpad/crashpad/client" ]
}
frameworks = [
libs = [
"AVFoundation.framework",
"Carbon.framework",
"LocalAuthentication.framework",
@@ -490,26 +481,19 @@ source_set("electron_lib") {
sources += [ "shell/browser/api/electron_api_app_mas.mm" ]
sources -= [ "shell/browser/auto_updater_mac.mm" ]
defines += [ "MAS_BUILD" ]
sources -= [
"shell/app/electron_crash_reporter_client.cc",
"shell/app/electron_crash_reporter_client.h",
"shell/common/crash_keys.cc",
"shell/common/crash_keys.h",
]
} else {
frameworks += [
libs += [
"Squirrel.framework",
"ReactiveObjC.framework",
"ReactiveCocoa.framework",
"Mantle.framework",
]
deps += [
"//third_party/squirrel.mac:reactiveobjc_framework+link",
"//third_party/squirrel.mac:squirrel_framework+link",
cflags_objcc = [
"-F",
rebase_path("external_binaries", root_build_dir),
]
# ReactiveObjC which is used by Squirrel requires using __weak.
cflags_objcc = [ "-fobjc-weak" ]
# ReactiveCocoa which is used by Squirrel requires using __weak.
cflags_objcc += [ "-fobjc-weak" ]
}
}
if (is_linux) {
@@ -539,16 +523,6 @@ source_set("electron_lib") {
sources += filenames.lib_sources_nss
sources += [
"shell/browser/ui/gtk/app_indicator_icon.cc",
"shell/browser/ui/gtk/app_indicator_icon.h",
"shell/browser/ui/gtk/app_indicator_icon_menu.cc",
"shell/browser/ui/gtk/app_indicator_icon_menu.h",
"shell/browser/ui/gtk/gtk_status_icon.cc",
"shell/browser/ui/gtk/gtk_status_icon.h",
"shell/browser/ui/gtk/menu_util.cc",
"shell/browser/ui/gtk/menu_util.h",
"shell/browser/ui/gtk/status_icon.cc",
"shell/browser/ui/gtk/status_icon.h",
"shell/browser/ui/gtk_util.cc",
"shell/browser/ui/gtk_util.h",
]
@@ -605,6 +579,15 @@ source_set("electron_lib") {
]
}
if (enable_remote_module) {
sources += [
"shell/common/api/remote/remote_callback_freer.cc",
"shell/common/api/remote/remote_callback_freer.h",
"shell/common/api/remote/remote_object_freer.cc",
"shell/common/api/remote/remote_object_freer.h",
]
}
if (enable_desktop_capturer) {
if (is_component_build && !is_linux) {
# On windows the implementation relies on unexported
@@ -663,7 +646,6 @@ source_set("electron_lib") {
deps += [
"//components/pdf/browser",
"//components/pdf/renderer",
"//pdf:pdf_ppapi",
]
sources += [
"shell/browser/electron_pdf_web_contents_helper_client.cc",
@@ -692,15 +674,6 @@ if (is_mac) {
sources = [ "shell/common/resources/mac/MainMenu.xib" ]
}
action("fake_v8_context_snapshot_generator") {
script = "build/fake_v8_context_snapshot_generator.py"
args = [
rebase_path("$root_out_dir/v8_context_snapshot.bin"),
rebase_path("$root_out_dir/fake/v8_context_snapshot.bin"),
]
outputs = [ "$root_out_dir/fake/v8_context_snapshot.bin" ]
}
bundle_data("electron_framework_resources") {
public_deps = [ ":packed_resources" ]
sources = []
@@ -711,13 +684,8 @@ if (is_mac) {
if (v8_use_external_startup_data) {
public_deps += [ "//v8" ]
if (use_v8_context_snapshot) {
if (use_prebuilt_v8_context_snapshot) {
sources += [ "$root_out_dir/fake/v8_context_snapshot.bin" ]
public_deps += [ ":fake_v8_context_snapshot_generator" ]
} else {
sources += [ "$root_out_dir/v8_context_snapshot.bin" ]
public_deps += [ "//tools/v8_context_snapshot" ]
}
sources += [ "$root_out_dir/v8_context_snapshot.bin" ]
public_deps += [ "//tools/v8_context_snapshot" ]
} else {
sources += [ "$root_out_dir/snapshot_blob.bin" ]
}
@@ -795,10 +763,8 @@ if (is_mac) {
framework_contents = [
"Resources",
"Libraries",
"Helpers",
]
if (!is_mas_build) {
framework_contents += [ "Helpers" ]
}
public_deps = [
":electron_framework_libraries",
":electron_lib",
@@ -822,19 +788,18 @@ if (is_mac) {
include_dirs = [ "." ]
sources = filenames.framework_sources
frameworks = []
libs = []
if (enable_osr) {
frameworks += [ "IOSurface.framework" ]
libs += [ "IOSurface.framework" ]
}
ldflags = [
"-F",
rebase_path("external_binaries", root_build_dir),
"-Wl,-install_name,@rpath/$output_name.framework/$output_name",
"-rpath",
"@loader_path/Libraries",
# Required for exporting all symbols of libuv.
"-Wl,-force_load,obj/third_party/electron_node/deps/uv/libuv.a",
]
if (is_component_build) {
ldflags += [
@@ -882,49 +847,17 @@ if (is_mac) {
}
}
template("stripped_framework") {
action(target_name) {
assert(defined(invoker.framework))
script = "//electron/build/strip_framework.py"
forward_variables_from(invoker, [ "deps" ])
inputs = [ "$root_out_dir/" + invoker.framework ]
outputs = [ "$target_out_dir/stripped_frameworks/" + invoker.framework ]
args = rebase_path(inputs) + rebase_path(outputs)
}
}
stripped_framework("stripped_mantle_framework") {
framework = "Mantle.framework"
deps = [ "//third_party/squirrel.mac:mantle_framework" ]
}
stripped_framework("stripped_reactiveobjc_framework") {
framework = "ReactiveObjC.framework"
deps = [ "//third_party/squirrel.mac:reactiveobjc_framework" ]
}
stripped_framework("stripped_squirrel_framework") {
framework = "Squirrel.framework"
deps = [ "//third_party/squirrel.mac:squirrel_framework" ]
}
bundle_data("electron_app_framework_bundle_data") {
sources = [ "$root_out_dir/$electron_framework_name.framework" ]
if (!is_mas_build) {
sources += get_target_outputs(":stripped_mantle_framework") +
get_target_outputs(":stripped_reactiveobjc_framework") +
get_target_outputs(":stripped_squirrel_framework")
sources += [
"external_binaries/Mantle.framework",
"external_binaries/ReactiveCocoa.framework",
"external_binaries/Squirrel.framework",
]
}
outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ]
public_deps = [
":electron_framework+link",
":stripped_mantle_framework",
":stripped_reactiveobjc_framework",
":stripped_squirrel_framework",
]
public_deps = [ ":electron_framework+link" ]
foreach(helper_params, content_mac_helpers) {
sources +=
@@ -937,7 +870,7 @@ if (is_mac) {
output_name = electron_login_helper_name
sources = filenames.login_helper_sources
include_dirs = [ "." ]
frameworks = [ "AppKit.framework" ]
libs = [ "AppKit.framework" ]
info_plist = "shell/app/resources/mac/loginhelper-Info.plist"
extra_substitutions =
[ "ELECTRON_BUNDLE_ID=$electron_mac_bundle_id.loginhelper" ]
@@ -1062,16 +995,13 @@ if (is_mac) {
group("electron_symbols") {
deps = [
":crashpad_handler_syms",
":electron_app_syms",
":electron_framework_syms",
":swiftshader_egl_syms",
":swiftshader_gles_syms",
]
if (!is_mas_build) {
deps += [ ":crashpad_handler_syms" ]
}
foreach(helper_params, content_mac_helpers) {
_helper_target = helper_params[0]
deps += [ ":electron_helper_syms_${_helper_target}" ]
@@ -1122,9 +1052,7 @@ if (is_mac) {
data += [ "$root_out_dir/resources/default_app.asar" ]
}
if (use_v8_context_snapshot) {
public_deps = [ "//tools/v8_context_snapshot:v8_context_snapshot" ]
}
public_deps = [ "//tools/v8_context_snapshot:v8_context_snapshot" ]
if (is_win) {
sources += [
@@ -1138,23 +1066,21 @@ if (is_mac) {
"//components/crash/core/app:run_as_crashpad_handler",
]
ldflags = []
libs = [
"comctl32.lib",
"uiautomationcore.lib",
"wtsapi32.lib",
]
configs += [
"//build/config/win:windowed",
"//build/config/win:delayloads",
]
configs += [ "//build/config/win:windowed" ]
if (target_cpu == "arm64") {
configs -= [ "//build/config/win:cfi_linker" ]
ldflags += [ "/guard:cf,nolongjmp" ]
}
ldflags = [
# Windows 7 doesn't have these DLLs.
# TODO: are there other DLLs we need to list here to be win7
# compatible?
"/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll",
"/DELAYLOAD:api-ms-win-core-winrt-string-l1-1-0.dll",
]
# This is to support renaming of electron.exe. node-gyp has hard-coded
# executable names which it will recognise as node. This module definition
@@ -1168,14 +1094,7 @@ if (is_mac) {
]
}
if (is_linux) {
ldflags = [
"-pie",
# Required for exporting all symbols of libuv.
"-Wl,--whole-archive",
"obj/third_party/electron_node/deps/uv/libuv.a",
"-Wl,--no-whole-archive",
]
ldflags = [ "-pie" ]
if (!is_component_build && is_component_ffmpeg) {
configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
@@ -1241,6 +1160,18 @@ test("shell_browser_ui_unittests") {
"//ui/base",
"//ui/strings",
]
if (is_mac) {
# Resolve paths owing to different test executable locations
ldflags = [
"-F",
rebase_path("external_binaries", root_build_dir),
"-rpath",
"@loader_path",
"-rpath",
"@executable_path/" + rebase_path("external_binaries", root_build_dir),
]
}
}
template("dist_zip") {
@@ -1338,13 +1269,10 @@ dist_zip("electron_chromedriver_zip") {
mksnapshot_deps = [
":licenses",
"//tools/v8_context_snapshot:v8_context_snapshot_generator($v8_snapshot_toolchain)",
"//v8:mksnapshot($v8_snapshot_toolchain)",
]
if (use_v8_context_snapshot) {
mksnapshot_deps += [ "//tools/v8_context_snapshot:v8_context_snapshot_generator($v8_snapshot_toolchain)" ]
}
group("electron_mksnapshot") {
public_deps = mksnapshot_deps
}

View File

@@ -47,17 +47,17 @@ dependencies, and tools contained in the `electron/electron` repository.
* [Step 1: Fork](https://electronjs.org/docs/development/pull-requests#step-1-fork)
* [Step 2: Build](https://electronjs.org/docs/development/pull-requests#step-2-build)
* [Step 3: Branch](https://electronjs.org/docs/development/pull-requests#step-3-branch)
* [Making Changes](https://electronjs.org/docs/development/pull-requests#making-changes)
* [The Process of Making Changes](https://electronjs.org/docs/development/pull-requests#the-process-of-making-changes)
* [Step 4: Code](https://electronjs.org/docs/development/pull-requests#step-4-code)
* [Step 5: Commit](https://electronjs.org/docs/development/pull-requests#step-5-commit)
* [Commit message guidelines](https://electronjs.org/docs/development/pull-requests#commit-message-guidelines)
* [Step 6: Rebase](https://electronjs.org/docs/development/pull-requests#step-6-rebase)
* [Step 7: Test](https://electronjs.org/docs/development/pull-requests#step-7-test)
* [Step 8: Push](https://electronjs.org/docs/development/pull-requests#step-8-push)
* [Step 9: Opening the Pull Request](https://electronjs.org/docs/development/pull-requests#step-9-opening-the-pull-request)
* [Step 10: Discuss and Update](https://electronjs.org/docs/development/pull-requests#step-10-discuss-and-update)
* [Step 8: Opening the Pull Request](https://electronjs.org/docs/development/pull-requests#step-8-opening-the-pull-request)
* [Step 9: Discuss and Update](#step-9-discuss-and-update)
* [Approval and Request Changes Workflow](https://electronjs.org/docs/development/pull-requests#approval-and-request-changes-workflow)
* [Step 11: Landing](https://electronjs.org/docs/development/pull-requests#step-11-landing)
* [Step 10: Landing](https://electronjs.org/docs/development/pull-requests#step-10-landing)
* [Continuous Integration Testing](https://electronjs.org/docs/development/pull-requests#continuous-integration-testing)
## Style Guides

35
DEPS
View File

@@ -5,22 +5,18 @@ gclient_gn_args = [
'checkout_android_native_support',
'checkout_libaom',
'checkout_nacl',
'checkout_pgo_profiles',
'checkout_oculus_sdk',
'checkout_openxr',
'checkout_google_benchmark',
'mac_xcode_version',
'checkout_google_benchmark'
]
vars = {
'chromium_version':
'87.0.4251.1',
'17da1064b910f4170320ff37e971064916aed1dc',
'node_version':
'v12.18.3',
'v12.16.3',
'nan_version':
'2c4ee8a32a299eada3cd6e468bbd0a473bfea96d',
'squirrel.mac_version':
'44468f858ce0d25c27bd5e674abfa104e0119738',
'boto_version': 'f7574aa6cc2c819430c1f05e9a1a1a666ef8169b',
'pyyaml_version': '3.12',
@@ -32,7 +28,6 @@ vars = {
'nodejs_git': 'https://github.com/nodejs',
'requests_git': 'https://github.com/kennethreitz',
'yaml_git': 'https://github.com/yaml',
'squirrel_git': 'https://github.com/Squirrel',
# KEEP IN SYNC WITH utils.js FILE
'yarn_version': '1.15.2',
@@ -47,7 +42,6 @@ vars = {
'checkout_chromium': True,
'checkout_node': True,
'checkout_nan': True,
'checkout_pgo_profiles': True,
# It's only needed to parse the native tests configurations.
'checkout_pyyaml': False,
@@ -55,8 +49,6 @@ vars = {
# Python "requests" module is used for releases only.
'checkout_requests': False,
'mac_xcode_version': 'default',
# To allow running hooks without parsing the DEPS tree
'process_deps': True,
@@ -107,18 +99,6 @@ deps = {
'url': Var('requests_git') + '/requests.git' + '@' + Var('requests_version'),
'condition': 'checkout_requests and process_deps',
},
'src/third_party/squirrel.mac': {
'url': Var("squirrel_git") + '/Squirrel.Mac.git@' + Var("squirrel.mac_version"),
'condition': 'process_deps',
},
'src/third_party/squirrel.mac/vendor/ReactiveObjC': {
'url': 'https://github.com/ReactiveCocoa/ReactiveObjC.git@74ab5baccc6f7202c8ac69a8d1e152c29dc1ea76',
'condition': 'process_deps'
},
'src/third_party/squirrel.mac/vendor/Mantle': {
'url': 'https://github.com/Mantle/Mantle.git@78d3966b3c331292ea29ec38661b25df0a245948',
'condition': 'process_deps',
}
}
hooks = [
@@ -127,7 +107,7 @@ hooks = [
'condition': '(checkout_chromium and apply_patches) and process_deps',
'pattern': 'src/electron',
'action': [
'python3',
'python',
'src/electron/script/apply_all_patches.py',
'src/electron/patches/config.json',
],
@@ -145,7 +125,7 @@ hooks = [
'name': 'electron_npm_deps',
'pattern': 'src/electron/package.json',
'action': [
'python3',
'python',
'-c',
'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python", "script/lib/npx.py", "yarn@' + (Var("yarn_version")) + '", "install", "--frozen-lockfile"]);',
],
@@ -155,7 +135,7 @@ hooks = [
'pattern': 'src/electron',
'condition': 'checkout_boto and process_deps',
'action': [
'python3',
'python',
'-c',
'import os, subprocess; os.chdir(os.path.join("src", "electron", "vendor", "boto")); subprocess.check_call(["python", "setup.py", "build"]);',
],
@@ -165,7 +145,7 @@ hooks = [
'pattern': 'src/electron',
'condition': 'checkout_requests and process_deps',
'action': [
'python3',
'python',
'-c',
'import os, subprocess; os.chdir(os.path.join("src", "electron", "vendor", "requests")); subprocess.check_call(["python", "setup.py", "build"]);',
],
@@ -174,5 +154,4 @@ hooks = [
recursedeps = [
'src',
'src/third_party/squirrel.mac',
]

View File

@@ -1 +1 @@
11.0.0-beta.10
10.0.0-beta.1

View File

@@ -6,11 +6,7 @@ To report a security issue, email [security@electronjs.org](mailto:security@elec
The Electron team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
Report security bugs in third-party modules to the person or team maintaining the module. You can also report a vulnerability through the [npm contact form](https://www.npmjs.com/support) by selecting "I'm reporting a security vulnerability".
## The Electron Security Notification Process
For context on Electron's security notification process, please see the [Notifications](https://github.com/electron/governance/blob/master/wg-security/membership-and-notifications.md#notifications) section of the Security WG's [Membership and Notifications](https://github.com/electron/governance/blob/master/wg-security/membership-and-notifications.md) Governance document.
Report security bugs in third-party modules to the person or team maintaining the module. You can also report a vulnerability through the [Node Security Project](https://nodesecurity.io/report).
## Learning More About Security
To learn more about securing an Electron application, please see the [security tutorial](docs/tutorial/security.md).

View File

@@ -29,7 +29,7 @@
version: 1.0.{build}
build_cloud: electron-16-core
image: vs2019bt-16.6.2
image: vs2019bt-16.4.0
environment:
GIT_CACHE_PATH: C:\Users\electron\libcc_cache
ELECTRON_OUT_DIR: Default
@@ -61,7 +61,6 @@ build_script:
- git config --global core.longpaths true
- cd ..
- mkdir src
- update_depot_tools.bat
- ps: Move-Item $env:APPVEYOR_BUILD_FOLDER -Destination src\electron
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
- ps: $env:SCCACHE_PATH="$pwd\src\electron\external_binaries\sccache.exe"

View File

@@ -1,104 +0,0 @@
steps:
- task: CopyFiles@2
displayName: 'Copy Files to: src/electron'
inputs:
TargetFolder: src/electron
- bash: |
cd src/electron
node script/yarn.js install --frozen-lockfile
displayName: 'Yarn install'
- bash: |
export ZIP_DEST=$PWD/src/out/Default
echo "##vso[task.setvariable variable=ZIP_DEST]$ZIP_DEST"
mkdir -p $ZIP_DEST
cd src/electron
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=dist.zip --dest=$ZIP_DEST
cd $ZIP_DEST
unzip -o dist.zip
displayName: 'Download and unzip dist files for test'
env:
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
- bash: |
export FFMPEG_ZIP_DEST=$PWD/src/out/ffmpeg
mkdir -p $FFMPEG_ZIP_DEST
cd src/electron
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=ffmpeg.zip --dest=$FFMPEG_ZIP_DEST
cd $FFMPEG_ZIP_DEST
unzip -o ffmpeg.zip
displayName: 'Download and unzip ffmpeg for test'
env:
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
- bash: |
export NODE_HEADERS_DEST=$PWD/src/out/Default/gen
mkdir -p $NODE_HEADERS_DEST
cd src/electron
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=node_headers.tar.gz --dest=$NODE_HEADERS_DEST
cd $NODE_HEADERS_DEST
tar xzf node_headers.tar.gz
displayName: 'Download and untar node header files for test'
env:
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
- bash: |
export CROSS_ARCH_SNAPSHOTS=$PWD/src/out/Default/cross-arch-snapshots
mkdir -p $CROSS_ARCH_SNAPSHOTS
cd src/electron
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=cross-arch-snapshots/snapshot_blob.bin --dest=$CROSS_ARCH_SNAPSHOTS
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=cross-arch-snapshots/v8_context_snapshot.bin --dest=$CROSS_ARCH_SNAPSHOTS
displayName: 'Download cross arch snapshot files'
env:
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
- bash: |
export NATIVE_UNITTESTS_DEST=$PWD/src/out/Default
cd src/electron
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=shell_browser_ui_unittests --dest=$NATIVE_UNITTESTS_DEST
chmod +x $NATIVE_UNITTESTS_DEST/shell_browser_ui_unittests
displayName: 'Download native unittest executables'
env:
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
- bash: |
cd src
export ELECTRON_OUT_DIR=Default
set npm_config_arch=arm64
(cd electron && node script/yarn test -- --enable-logging)
displayName: 'Run Electron tests'
timeoutInMinutes: 20
env:
ELECTRON_DISABLE_SECURITY_WARNINGS: 1
IGNORE_YARN_INSTALL_ERROR: 1
ELECTRON_TEST_RESULTS_DIR: junit
- bash: |
cd src
python electron/script/verify-ffmpeg.py --source-root "$PWD" --build-dir out/Default --ffmpeg-path out/ffmpeg
displayName: Verify non proprietary ffmpeg
timeoutInMinutes: 5
condition: succeededOrFailed()
- bash: |
cd src
echo Verify cross arch snapshot
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --snapshot-files-dir $PWD/out/Default/cross-arch-snapshots
displayName: Verify cross arch snapshot
timeoutInMinutes: 5
condition: succeededOrFailed()
- task: PublishTestResults@2
displayName: 'Publish Test Results'
inputs:
testResultsFiles: '*.xml'
searchFolder: '$(System.DefaultWorkingDirectory)/src/junit/'
condition: succeededOrFailed()
- task: mspremier.PostBuildCleanup.PostBuildCleanup-task.PostBuildCleanup@3
displayName: 'Clean Agent Directories'
condition: always()

View File

@@ -71,6 +71,7 @@ steps:
ELECTRON_TEST_RESULTS_DIR: junit
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
MOCHA_REPORTER: mocha-multi-reporters
MOCHA_TIMEOUT: 120000
- task: PublishTestResults@2
displayName: 'Publish Test Results'
@@ -87,11 +88,7 @@ steps:
- powershell: |
Get-Process | Where Name Like "electron*" | Stop-Process
Get-Process | Where Name Like "MicrosoftEdge*" | Stop-Process
Get-Process | Where Name Like "msedge*" | Stop-Process
displayName: 'Kill processes left running from last test run'
condition: always()
- powershell: |
Remove-Item -path $env:APPDATA/Electron* -Recurse
displayName: 'Delete user app data directories'
condition: always()

View File

@@ -1,8 +0,0 @@
import os
import shutil
import sys
if os.path.exists(sys.argv[2]):
os.remove(sys.argv[2])
shutil.copy(sys.argv[1], sys.argv[2])

View File

@@ -1,16 +0,0 @@
#!/usr/bin/env python
import os
import subprocess
import sys
source = sys.argv[1]
dest = sys.argv[2]
# Ensure any existing framework is removed
subprocess.check_output(["rm", "-rf", dest])
subprocess.check_output(["cp", "-a", source, dest])
# Strip headers, we do not need to ship them
subprocess.check_output(["rm", "-r", os.path.join(dest, 'Headers')])
subprocess.check_output(["rm", "-r", os.path.join(dest, 'Versions', 'Current', 'Headers')])

View File

@@ -1,2 +1,2 @@
process.env.PRINT_WEBPACK_GRAPH = true;
require('./run-compiler');
process.env.PRINT_WEBPACK_GRAPH = true
require('./run-compiler')

View File

@@ -1,45 +1,22 @@
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const path = require('path')
const webpack = require('webpack')
const configPath = process.argv[2];
const outPath = path.resolve(process.argv[3]);
const config = require(configPath);
const configPath = process.argv[2]
const outPath = path.resolve(process.argv[3])
const config = require(configPath)
config.output = {
path: path.dirname(outPath),
filename: path.basename(outPath)
};
}
const { wrapInitWithProfilingTimeout, wrapInitWithTryCatch, ...webpackConfig } = config;
webpack(webpackConfig, (err, stats) => {
webpack(config, (err, stats) => {
if (err) {
console.error(err);
process.exit(1);
console.error(err)
process.exit(1)
} else if (stats.hasErrors()) {
console.error(stats.toString('normal'));
process.exit(1);
console.error(stats.toString('normal'))
process.exit(1)
} else {
let contents = fs.readFileSync(outPath, 'utf8');
if (wrapInitWithTryCatch) {
contents = `try {
${contents}
} catch (err) {
console.error('Electron ${webpackConfig.output.filename} script failed to run');
console.error(err);
}`;
}
if (wrapInitWithProfilingTimeout) {
contents = `function ___electron_webpack_init__() {
${contents}
};
if ((globalThis.process || binding.process).argv.includes("--profile-electron-init")) {
setTimeout(___electron_webpack_init__, 0);
} else {
___electron_webpack_init__();
}`;
}
fs.writeFileSync(outPath, contents);
process.exit(0);
process.exit(0)
}
});
})

View File

@@ -1,5 +0,0 @@
module.exports = require('./webpack.config.base')({
target: 'asar',
alwaysHasNode: true,
targetDeletesNodeGlobals: true
});

View File

@@ -1,120 +1,111 @@
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
const fs = require('fs')
const path = require('path')
const webpack = require('webpack')
const electronRoot = path.resolve(__dirname, '../..');
const electronRoot = path.resolve(__dirname, '../..')
const onlyPrintingGraph = !!process.env.PRINT_WEBPACK_GRAPH;
const onlyPrintingGraph = !!process.env.PRINT_WEBPACK_GRAPH
class AccessDependenciesPlugin {
apply (compiler) {
apply(compiler) {
// Only hook into webpack when we are printing the dependency graph
if (!onlyPrintingGraph) return;
if (!onlyPrintingGraph) return
compiler.hooks.compilation.tap('AccessDependenciesPlugin', compilation => {
compilation.hooks.finishModules.tap('AccessDependenciesPlugin', modules => {
const filePaths = modules.map(m => m.resource).filter(p => p).map(p => path.relative(electronRoot, p));
console.info(JSON.stringify(filePaths));
});
});
const filePaths = modules.map(m => m.resource).filter(p => p).map(p => path.relative(electronRoot, p))
console.info(JSON.stringify(filePaths))
})
})
}
}
const defines = {
BUILDFLAG: onlyPrintingGraph ? '(a => a)' : ''
};
BUILDFLAG: ''
}
const buildFlagsPrefix = '--buildflags=';
const buildFlagsPrefix = '--buildflags='
const buildFlagArg = process.argv.find(arg => arg.startsWith(buildFlagsPrefix));
if (buildFlagArg) {
const buildFlagPath = buildFlagArg.substr(buildFlagsPrefix.length);
const buildFlagPath = buildFlagArg.substr(buildFlagsPrefix.length)
const flagFile = fs.readFileSync(buildFlagPath, 'utf8');
const flagFile = fs.readFileSync(buildFlagPath, 'utf8')
for (const line of flagFile.split(/(\r\n|\r|\n)/g)) {
const flagMatch = line.match(/#define BUILDFLAG_INTERNAL_(.+?)\(\) \(([01])\)/);
const flagMatch = line.match(/#define BUILDFLAG_INTERNAL_(.+?)\(\) \(([01])\)/)
if (flagMatch) {
const [, flagName, flagValue] = flagMatch;
const flagName = flagMatch[1];
const flagValue = flagMatch[2];
defines[flagName] = JSON.stringify(Boolean(parseInt(flagValue, 10)));
}
}
}
const ignoredModules = [];
const ignoredModules = []
if (defines.ENABLE_DESKTOP_CAPTURER === 'false') {
if (defines['ENABLE_DESKTOP_CAPTURER'] === 'false') {
ignoredModules.push(
'@electron/internal/browser/desktop-capturer',
'@electron/internal/browser/api/desktop-capturer',
'@electron/internal/renderer/api/desktop-capturer'
);
)
}
if (defines.ENABLE_REMOTE_MODULE === 'false') {
if (defines['ENABLE_REMOTE_MODULE'] === 'false') {
ignoredModules.push(
'@electron/internal/browser/remote/server',
'@electron/internal/renderer/api/remote'
);
)
}
if (defines.ENABLE_VIEWS_API === 'false') {
if (defines['ENABLE_VIEWS_API'] === 'false') {
ignoredModules.push(
'@electron/internal/browser/api/views/image-view.js'
);
)
}
const alias = {}
for (const ignoredModule of ignoredModules) {
alias[ignoredModule] = path.resolve(electronRoot, 'lib/common/dummy.js')
}
module.exports = ({
alwaysHasNode,
loadElectronFromAlternateTarget,
targetDeletesNodeGlobals,
target,
wrapInitWithProfilingTimeout,
wrapInitWithTryCatch
target
}) => {
let entry = path.resolve(electronRoot, 'lib', target, 'init.ts');
let entry = path.resolve(electronRoot, 'lib', target, 'init.ts')
if (!fs.existsSync(entry)) {
entry = path.resolve(electronRoot, 'lib', target, 'init.js');
entry = path.resolve(electronRoot, 'lib', target, 'init.js')
}
const electronAPIFile = path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.ts');
return ({
mode: 'development',
devtool: false,
devtool: 'inline-source-map',
entry,
target: alwaysHasNode ? 'node' : 'web',
output: {
filename: `${target}.bundle.js`
},
wrapInitWithProfilingTimeout,
wrapInitWithTryCatch,
resolve: {
alias: {
...alias,
'@electron/internal': path.resolve(electronRoot, 'lib'),
electron$: electronAPIFile,
'electron/main$': electronAPIFile,
'electron/renderer$': electronAPIFile,
'electron/common$': electronAPIFile,
// Force timers to resolve to our dependency that doesn't use window.postMessage
timers: path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
'electron': path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.ts'),
// Force timers to resolve to our dependency that doens't use window.postMessage
'timers': path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
},
extensions: ['.ts', '.js']
},
module: {
rules: [{
test: (moduleName) => !onlyPrintingGraph && ignoredModules.includes(moduleName),
loader: 'null-loader'
}, {
test: /\.ts$/,
loader: 'ts-loader',
options: {
configFile: path.resolve(electronRoot, 'tsconfig.electron.json'),
transpileOnly: onlyPrintingGraph,
ignoreDiagnostics: [
// File '{0}' is not under 'rootDir' '{1}'.
6059
]
ignoreDiagnostics: [6059]
}
}]
},
@@ -123,32 +114,21 @@ module.exports = ({
__filename: false,
// We provide our own "timers" import above, any usage of setImmediate inside
// one of our renderer bundles should import it from the 'timers' package
setImmediate: false
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
keep_classnames: true,
keep_fnames: true
}
})
]
setImmediate: false,
},
plugins: [
new AccessDependenciesPlugin(),
...(targetDeletesNodeGlobals ? [
new webpack.ProvidePlugin({
process: ['@electron/internal/common/webpack-provider', 'process'],
global: ['@electron/internal/common/webpack-provider', '_global'],
Buffer: ['@electron/internal/common/webpack-provider', 'Buffer']
process: ['@electron/internal/renderer/webpack-provider', 'process'],
global: ['@electron/internal/renderer/webpack-provider', '_global'],
Buffer: ['@electron/internal/renderer/webpack-provider', 'Buffer'],
})
] : []),
new webpack.ProvidePlugin({
Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise']
Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise'],
}),
new webpack.DefinePlugin(defines)
new webpack.DefinePlugin(defines),
]
});
};
})
}

View File

@@ -1,4 +1,4 @@
module.exports = require('./webpack.config.base')({
target: 'browser',
alwaysHasNode: true
});
})

View File

@@ -1,5 +1,4 @@
module.exports = require('./webpack.config.base')({
target: 'isolated_renderer',
alwaysHasNode: false,
wrapInitWithTryCatch: true
});
alwaysHasNode: false
})

View File

@@ -1,7 +1,5 @@
module.exports = require('./webpack.config.base')({
target: 'renderer',
alwaysHasNode: true,
targetDeletesNodeGlobals: true,
wrapInitWithProfilingTimeout: true,
wrapInitWithTryCatch: true
});
targetDeletesNodeGlobals: true
})

View File

@@ -1,6 +1,4 @@
module.exports = require('./webpack.config.base')({
target: 'sandboxed_renderer',
alwaysHasNode: false,
wrapInitWithProfilingTimeout: true,
wrapInitWithTryCatch: true
});
alwaysHasNode: false
})

View File

@@ -2,6 +2,5 @@ module.exports = require('./webpack.config.base')({
target: 'worker',
loadElectronFromAlternateTarget: 'renderer',
alwaysHasNode: true,
targetDeletesNodeGlobals: true,
wrapInitWithTryCatch: true
});
targetDeletesNodeGlobals: true
})

View File

@@ -16,7 +16,6 @@ template("webpack_build") {
inputs = [
invoker.config_file,
"//electron/build/webpack/webpack.config.base.js",
"//electron/build/webpack/run-compiler.js",
"//electron/tsconfig.json",
"//electron/yarn.lock",
"//electron/typings/internal-ambient.d.ts",

View File

@@ -32,8 +32,6 @@ PATHS_TO_SKIP = [
# On Linux, we don't use crashpad, but this binary is still built for some
# reason. Exclude it from the zip.
'./crashpad_handler',
'resources/inspector', #Skipping because these are outputs that we don't need
]
def skip_path(dep, dist_zip, target_cpu):

View File

@@ -12,8 +12,6 @@ import("//third_party/widevine/cdm/widevine.gni")
static_library("chrome") {
visibility = [ "//electron:electron_lib" ]
sources = [
"//chrome/browser/accessibility/accessibility_ui.cc",
"//chrome/browser/accessibility/accessibility_ui.h",
"//chrome/browser/browser_process.cc",
"//chrome/browser/browser_process.h",
"//chrome/browser/crash_upload_list/crash_upload_list_crashpad.cc",
@@ -64,20 +62,17 @@ static_library("chrome") {
"//extensions/browser/app_window/size_constraints.cc",
"//extensions/browser/app_window/size_constraints.h",
]
public_deps = [
"//chrome/common",
"//chrome/common:version_header",
"//components/keyed_service/content",
"//components/paint_preview/buildflags",
"//components/proxy_config",
"//components/security_state/content",
"//content/public/browser",
]
deps = [
"//chrome/browser:resource_prefetch_predictor_proto",
"//chrome/services/speech:buildflags",
"//components/feature_engagement:buildflags",
"//components/optimization_guide/proto:optimization_guide_proto",
]
@@ -97,14 +92,6 @@ static_library("chrome") {
]
}
if (is_win) {
sources += [
"//chrome/browser/win/icon_reader_service.cc",
"//chrome/browser/win/icon_reader_service.h",
]
public_deps += [ "//chrome/services/util_win:lib" ]
}
if (enable_desktop_capturer) {
sources += [
"//chrome/browser/media/webrtc/desktop_media_list.h",
@@ -165,6 +152,13 @@ static_library("chrome") {
}
}
if (enable_tts) {
sources += [
"//chrome/browser/speech/tts_controller_delegate_impl.cc",
"//chrome/browser/speech/tts_controller_delegate_impl.h",
]
}
if (enable_widevine) {
sources += [
"//chrome/renderer/media/chrome_key_systems.cc",
@@ -271,7 +265,7 @@ static_library("chrome") {
source_set("plugins") {
sources = []
deps = []
frameworks = []
libs = []
# browser side
sources += [
@@ -305,7 +299,7 @@ source_set("plugins") {
"//chrome/browser/renderer_host/pepper/monitor_finder_mac.h",
"//chrome/browser/renderer_host/pepper/monitor_finder_mac.mm",
]
frameworks += [ "CoreGraphics.framework" ]
libs += [ "CoreGraphics.framework" ]
}
if (is_linux) {
deps += [ "//components/services/font/public/cpp" ]
@@ -369,8 +363,8 @@ source_set("chrome_spellchecker") {
"//chrome/browser/spellchecker/spellcheck_factory.h",
"//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc",
"//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h",
"//chrome/browser/spellchecker/spellcheck_language_blocklist_policy_handler.cc",
"//chrome/browser/spellchecker/spellcheck_language_blocklist_policy_handler.h",
"//chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.cc",
"//chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.h",
"//chrome/browser/spellchecker/spellcheck_language_policy_handler.cc",
"//chrome/browser/spellchecker/spellcheck_language_policy_handler.h",
"//chrome/browser/spellchecker/spellcheck_service.cc",

View File

@@ -36,7 +36,6 @@ net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
// Linux has only a single persistent slot compared to ChromeOS's separate
// public and private slot.
// Redirect any slot usage to this persistent slot on Linux.
crypto::EnsureNSSInit();
g_nss_cert_database = new net::NSSCertDatabase(
crypto::ScopedPK11Slot(PK11_GetInternalKeySlot()) /* public slot */,
crypto::ScopedPK11Slot(PK11_GetInternalKeySlot()) /* private slot */);

View File

@@ -68,6 +68,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/posix/eintr_wrapper.h"
@@ -360,7 +361,7 @@ bool CheckCookie(const base::FilePath& path, const base::FilePath& cookie) {
}
bool IsAppSandboxed() {
#if defined(OS_MAC)
#if defined(OS_MACOSX)
// NB: There is no sane API for this, we have to just guess by
// reading tea leaves
base::FilePath home_dir;
@@ -371,7 +372,7 @@ bool IsAppSandboxed() {
return home_dir.value().find("Library/Containers") != std::string::npos;
#else
return false;
#endif // defined(OS_MAC)
#endif // defined(OS_MACOSX)
}
bool ConnectSocket(ScopedSocket* socket,
@@ -421,7 +422,7 @@ bool ConnectSocket(ScopedSocket* socket,
}
}
#if defined(OS_MAC)
#if defined(OS_MACOSX)
bool ReplaceOldSingletonLock(const base::FilePath& symlink_content,
const base::FilePath& lock_path) {
// Try taking an flock(2) on the file. Failure means the lock is taken so we
@@ -447,14 +448,14 @@ bool ReplaceOldSingletonLock(const base::FilePath& symlink_content,
// lock. We never flock() the lock file from now on. I.e. we assume that an
// old version of Chrome will not run with the same user data dir after this
// version has run.
if (!base::DeleteFile(lock_path)) {
if (!base::DeleteFile(lock_path, false)) {
PLOG(ERROR) << "Could not delete old singleton lock.";
return false;
}
return SymlinkPath(symlink_content, lock_path);
}
#endif // defined(OS_MAC)
#endif // defined(OS_MACOSX)
} // namespace
@@ -970,7 +971,7 @@ bool ProcessSingleton::Create() {
if (!SymlinkPath(symlink_content, lock_path_)) {
// TODO(jackhou): Remove this case once this code is stable on Mac.
// http://crbug.com/367612
#if defined(OS_MAC)
#if defined(OS_MACOSX)
// On Mac, an existing non-symlink lock file means the lock could be held by
// the old process singleton code. If we can successfully replace the lock,
// continue as normal.

View File

@@ -24,18 +24,18 @@ GlobalMenuBarRegistrarX11* GlobalMenuBarRegistrarX11::GetInstance() {
return base::Singleton<GlobalMenuBarRegistrarX11>::get();
}
void GlobalMenuBarRegistrarX11::OnWindowMapped(x11::Window window) {
live_windows_.insert(window);
void GlobalMenuBarRegistrarX11::OnWindowMapped(unsigned long xid) {
live_xids_.insert(xid);
if (registrar_proxy_)
RegisterXWindow(window);
RegisterXID(xid);
}
void GlobalMenuBarRegistrarX11::OnWindowUnmapped(x11::Window window) {
void GlobalMenuBarRegistrarX11::OnWindowUnmapped(unsigned long xid) {
if (registrar_proxy_)
UnregisterXWindow(window);
UnregisterXID(xid);
live_windows_.erase(window);
live_xids_.erase(xid);
}
GlobalMenuBarRegistrarX11::GlobalMenuBarRegistrarX11()
@@ -63,9 +63,9 @@ GlobalMenuBarRegistrarX11::~GlobalMenuBarRegistrarX11() {
}
}
void GlobalMenuBarRegistrarX11::RegisterXWindow(x11::Window window) {
void GlobalMenuBarRegistrarX11::RegisterXID(unsigned long xid) {
DCHECK(registrar_proxy_);
std::string path = electron::GlobalMenuBarX11::GetPathForWindow(window);
std::string path = electron::GlobalMenuBarX11::GetPathForWindow(xid);
ANNOTATE_SCOPED_MEMORY_LEAK; // http://crbug.com/314087
// TODO(erg): The mozilla implementation goes to a lot of callback trouble
@@ -76,13 +76,13 @@ void GlobalMenuBarRegistrarX11::RegisterXWindow(x11::Window window) {
// I don't see any reason why we should care if "RegisterWindow" completes or
// not.
g_dbus_proxy_call(registrar_proxy_, "RegisterWindow",
g_variant_new("(uo)", window, path.c_str()),
g_variant_new("(uo)", xid, path.c_str()),
G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr, nullptr);
}
void GlobalMenuBarRegistrarX11::UnregisterXWindow(x11::Window window) {
void GlobalMenuBarRegistrarX11::UnregisterXID(unsigned long xid) {
DCHECK(registrar_proxy_);
std::string path = electron::GlobalMenuBarX11::GetPathForWindow(window);
std::string path = electron::GlobalMenuBarX11::GetPathForWindow(xid);
ANNOTATE_SCOPED_MEMORY_LEAK; // http://crbug.com/314087
// TODO(erg): The mozilla implementation goes to a lot of callback trouble
@@ -93,7 +93,7 @@ void GlobalMenuBarRegistrarX11::UnregisterXWindow(x11::Window window) {
// I don't see any reason why we should care if "UnregisterWindow" completes
// or not.
g_dbus_proxy_call(registrar_proxy_, "UnregisterWindow",
g_variant_new("(u)", window), G_DBUS_CALL_FLAGS_NONE, -1,
g_variant_new("(u)", xid), G_DBUS_CALL_FLAGS_NONE, -1,
nullptr, nullptr, nullptr);
}
@@ -120,10 +120,10 @@ void GlobalMenuBarRegistrarX11::OnProxyCreated(GObject* source,
void GlobalMenuBarRegistrarX11::OnNameOwnerChanged(GObject* /* ignored */,
GParamSpec* /* ignored */) {
// If the name owner changed, we need to reregister all the live x11::Window
// with the system.
for (std::set<x11::Window>::const_iterator it = live_windows_.begin();
it != live_windows_.end(); ++it) {
RegisterXWindow(*it);
// If the name owner changed, we need to reregister all the live xids with
// the system.
for (std::set<unsigned long>::const_iterator it = live_xids_.begin();
it != live_xids_.end(); ++it) {
RegisterXID(*it);
}
}

View File

@@ -12,20 +12,19 @@
#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h"
#include "ui/base/glib/glib_signal.h"
#include "ui/gfx/x/xproto.h"
// Advertises our menu bars to Unity.
//
// GlobalMenuBarX11 is responsible for managing the DbusmenuServer for each
// x11::Window. We need a separate object to own the dbus channel to
// XID. We need a separate object to own the dbus channel to
// com.canonical.AppMenu.Registrar and to register/unregister the mapping
// between a x11::Window and the DbusmenuServer instance we are offering.
// between a XID and the DbusmenuServer instance we are offering.
class GlobalMenuBarRegistrarX11 {
public:
static GlobalMenuBarRegistrarX11* GetInstance();
void OnWindowMapped(x11::Window window);
void OnWindowUnmapped(x11::Window window);
void OnWindowMapped(unsigned long xid);
void OnWindowUnmapped(unsigned long xid);
private:
friend struct base::DefaultSingletonTraits<GlobalMenuBarRegistrarX11>;
@@ -34,8 +33,8 @@ class GlobalMenuBarRegistrarX11 {
~GlobalMenuBarRegistrarX11();
// Sends the actual message.
void RegisterXWindow(x11::Window window);
void UnregisterXWindow(x11::Window window);
void RegisterXID(unsigned long xid);
void UnregisterXID(unsigned long xid);
CHROMEG_CALLBACK_1(GlobalMenuBarRegistrarX11,
void,
@@ -50,9 +49,9 @@ class GlobalMenuBarRegistrarX11 {
GDBusProxy* registrar_proxy_;
// x11::Window which want to be registered, but haven't yet been because
// Window XIDs which want to be registered, but haven't yet been because
// we're waiting for the proxy to become available.
std::set<x11::Window> live_windows_;
std::set<unsigned long> live_xids_;
DISALLOW_COPY_AND_ASSIGN(GlobalMenuBarRegistrarX11);
};

View File

@@ -1,6 +1,5 @@
import { app, dialog, BrowserWindow, shell, ipcMain } from 'electron';
import * as path from 'path';
import * as url from 'url';
let mainWindow: BrowserWindow | null = null;
@@ -30,11 +29,12 @@ function isTrustedSender (webContents: Electron.WebContents) {
return false;
}
try {
return url.fileURLToPath(webContents.getURL()) === indexPath;
} catch {
return false;
}
const parsedUrl = new URL(webContents.getURL());
const urlPath = process.platform === 'win32'
// Strip the prefixed "/" that occurs on windows
? path.resolve(parsedUrl.pathname.substr(1))
: parsedUrl.pathname;
return parsedUrl.protocol === 'file:' && urlPath === indexPath;
}
ipcMain.handle('bootstrap', (event) => {

View File

@@ -53,31 +53,31 @@
<nav>
<div class="linkcol">
<a class="hero-link" target="_blank" href="https://electronjs.org/blog">
<span class="octicon hero-octicon octicon-code-square-24" aria-hidden="true"></span>
<span class="octicon hero-octicon octicon-gist" aria-hidden="true"></span>
<h4>Blog</h4>
</a>
</div>
<div class="linkcol">
<a class="hero-link" target="_blank" href="https://github.com/electron/electron">
<span class="octicon hero-octicon octicon-mark-github-16" aria-hidden="true"></span>
<span class="octicon hero-octicon octicon-mark-github" aria-hidden="true"></span>
<h4>Repository</h4>
</a>
</div>
<div class="linkcol">
<a class="hero-link" target="_blank" href="https://electronjs.org/docs">
<span class="octicon hero-octicon octicon-book-24" aria-hidden="true"></span>
<span class="octicon hero-octicon octicon-gear" aria-hidden="true"></span>
<h4>Docs</h4>
</a>
</div>
<div class="linkcol">
<a class="hero-link" target="_blank" href="https://github.com/electron/electron-api-demos">
<span class="octicon hero-octicon octicon-star-fill-24" aria-hidden="true"></span>
<span class="octicon hero-octicon octicon-star" aria-hidden="true"></span>
<h4>API Demos</h4>
</a>
</div>
<div class="linkcol">
<a class="hero-link" target="_blank" href="https://electronforge.io">
<span class="octicon hero-octicon octicon-gift-24" aria-hidden="true"></span>
<span class="octicon hero-octicon octicon-gift" aria-hidden="true"></span>
<h4>Forge</h4>
</a>
</div>

View File

@@ -1,9 +1,8 @@
import * as electron from 'electron';
import { app, dialog } from 'electron';
import * as fs from 'fs';
import * as path from 'path';
import * as url from 'url';
const { app, dialog } = electron;
type DefaultAppOptions = {
file: null | string;
@@ -146,90 +145,13 @@ function startRepl () {
process.exit(1);
}
// Prevent quitting.
// prevent quitting
app.on('window-all-closed', () => {});
const GREEN = '32';
const colorize = (color: string, s: string) => `\x1b[${color}m${s}\x1b[0m`;
const electronVersion = colorize(GREEN, `v${process.versions.electron}`);
const nodeVersion = colorize(GREEN, `v${process.versions.node}`);
console.info(`
Welcome to the Electron.js REPL \\[._.]/
You can access all Electron.js modules here as well as Node.js modules.
Using: Node.js ${nodeVersion} and Electron.js ${electronVersion}
`);
const { REPLServer } = require('repl');
const repl = new REPLServer({
prompt: '> '
}).on('exit', () => {
const repl = require('repl');
repl.start('> ').on('exit', () => {
process.exit(0);
});
function defineBuiltin (context: any, name: string, getter: Function) {
const setReal = (val: any) => {
// Deleting the property before re-assigning it disables the
// getter/setter mechanism.
delete context[name];
context[name] = val;
};
Object.defineProperty(context, name, {
get: () => {
const lib = getter();
delete context[name];
Object.defineProperty(context, name, {
get: () => lib,
set: setReal,
configurable: true,
enumerable: false
});
return lib;
},
set: setReal,
configurable: true,
enumerable: false
});
}
defineBuiltin(repl.context, 'electron', () => electron);
for (const api of Object.keys(electron) as (keyof typeof electron)[]) {
defineBuiltin(repl.context, api, () => electron[api]);
}
// Copied from node/lib/repl.js. For better DX, we don't want to
// show e.g 'contentTracing' at a higher priority than 'const', so
// we only trigger custom tab-completion when no common words are
// potentially matches.
const commonWords = [
'async', 'await', 'break', 'case', 'catch', 'const', 'continue',
'debugger', 'default', 'delete', 'do', 'else', 'export', 'false',
'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'let',
'new', 'null', 'return', 'switch', 'this', 'throw', 'true', 'try',
'typeof', 'var', 'void', 'while', 'with', 'yield'
];
const electronBuiltins = [...Object.keys(electron), 'original-fs', 'electron'];
const defaultComplete = repl.completer;
repl.completer = (line: string, callback: Function) => {
const lastSpace = line.lastIndexOf(' ');
const currentSymbol = line.substring(lastSpace + 1, repl.cursor);
const filterFn = (c: string) => c.startsWith(currentSymbol);
const ignores = commonWords.filter(filterFn);
const hits = electronBuiltins.filter(filterFn);
if (!ignores.length && hits.length) {
callback(null, [hits, currentSymbol]);
} else {
defaultComplete.apply(repl, [line, callback]);
}
};
}
// Start the specified app if there is one specified in command line, otherwise

View File

@@ -92,6 +92,7 @@ These individual tutorials expand on topics discussed in the guide above.
* Electron Releases & Developer Feedback
* [Versioning Policy](tutorial/electron-versioning.md)
* [Release Timelines](tutorial/electron-timelines.md)
* [App Feedback Program](tutorial/app-feedback-program.md)
* [Packaging App Source Code with asar](tutorial/application-packaging.md)
* [Generating asar Archives](tutorial/application-packaging.md#generating-asar-archives)
* [Using asar Archives](tutorial/application-packaging.md#using-asar-archives)

View File

@@ -140,16 +140,6 @@ this event, such as launching the application for the first time, attempting
to re-launch the application when it's already running, or clicking on the
application's dock or taskbar icon.
### Event: 'did-become-active' _macOS_
Returns:
* `event` Event
Emitted when mac application become active. Difference from `activate` event is
that `did-become-active` is emitted every time the app becomes active, not only
when Dock icon is clicked or application is re-launched.
### Event: 'continue-activity' _macOS_
Returns:
@@ -360,7 +350,7 @@ page.
Emitted whenever there is a GPU info update.
### Event: 'gpu-process-crashed' _Deprecated_
### Event: 'gpu-process-crashed'
Returns:
@@ -369,12 +359,7 @@ Returns:
Emitted when the GPU process crashes or is killed.
**Deprecated:** This event is superceded by the `child-process-gone` event
which contains more information about why the child process disappeared. It
isn't always because it crashed. The `killed` boolean can be replaced by
checking `reason === 'killed'` when you switch to that event.
### Event: 'renderer-process-crashed' _Deprecated_
### Event: 'renderer-process-crashed'
Returns:
@@ -385,7 +370,7 @@ Returns:
Emitted when the renderer process of `webContents` crashes or is killed.
**Deprecated:** This event is superceded by the `render-process-gone` event
which contains more information about why the render process disappeared. It
which contains more information about why the render process dissapeared. It
isn't always because it crashed. The `killed` boolean can be replaced by
checking `reason === 'killed'` when you switch to that event.
@@ -405,39 +390,9 @@ Returns:
* `launch-failure` - Process never successfully launched
* `integrity-failure` - Windows code integrity checks failed
Emitted when the renderer process unexpectedly disappears. This is normally
Emitted when the renderer process unexpectedly dissapears. This is normally
because it was crashed or killed.
#### Event: 'child-process-gone'
Returns:
* `event` Event
* `details` Object
* `type` String - Process type. One of the following values:
* `Utility`
* `Zygote`
* `Sandbox helper`
* `GPU`
* `Pepper Plugin`
* `Pepper Plugin Broker`
* `Unknown`
* `reason` String - The reason the child process is gone. Possible values:
* `clean-exit` - Process exited with an exit code of zero
* `abnormal-exit` - Process exited with a non-zero exit code
* `killed` - Process was sent a SIGTERM or otherwise killed externally
* `crashed` - Process crashed
* `oom` - Process ran out of memory
* `launch-failure` - Process never successfully launched
* `integrity-failure` - Windows code integrity checks failed
* `exitCode` Number - The exit code for the process
(e.g. status from waitpid if on posix, from GetExitCodeProcess on Windows).
* `name` String (optional) - The name of the process. i.e. for plugins it might be Flash.
Examples for utility: `Audio Service`, `Content Decryption Module Service`, `Network Service`, `Video Capture`, etc.
Emitted when the child process unexpectedly disappears. This is normally
because it was crashed or killed. It does not include renderer processes.
### Event: 'accessibility-support-changed' _macOS_ _Windows_
Returns:
@@ -850,20 +805,6 @@ Returns `String` - Name of the application handling the protocol, or an empty
This method returns the application name of the default handler for the protocol
(aka URI scheme) of a URL.
### `app.getApplicationInfoForProtocol(url)` _macOS_ _Windows_
* `url` String - a URL with the protocol name to check. Unlike the other
methods in this family, this accepts an entire URL, including `://` at a
minimum (e.g. `https://`).
Returns `Promise<Object>` - Resolve with an object containing the following:
* `icon` NativeImage - the display icon of the app handling the protocol.
* `path` String - installation path of the app handling the protocol.
* `name` String - display name of the app handling the protocol.
This method returns a promise that contains the application name, icon and path of the default handler for the protocol
(aka URI scheme) of a URL.
### `app.setUserTasks(tasks)` _Windows_
* `tasks` [Task[]](structures/task.md) - Array of `Task` objects
@@ -1025,7 +966,6 @@ if (!gotTheLock) {
// Create myWindow, load the rest of the app, etc...
app.whenReady().then(() => {
myWindow = createWindow()
})
}
```
@@ -1141,10 +1081,8 @@ For `infoType` equal to `complete`:
For `infoType` equal to `basic`:
Promise is fulfilled with `Object` containing fewer attributes than when requested with `complete`. Here's an example of basic response:
```js
{
auxAttributes:
{
amdSwitchable: true,
{ auxAttributes:
{ amdSwitchable: true,
canSupportThreadedTextureMailbox: false,
directComposition: false,
directRendering: true,
@@ -1157,14 +1095,12 @@ For `infoType` equal to `basic`:
sandboxed: false,
softwareRendering: false,
supportsOverlays: false,
videoDecodeAcceleratorFlags: 0
},
gpuDevice:
[{ active: true, deviceId: 26657, vendorId: 4098 },
{ active: false, deviceId: 3366, vendorId: 32902 }],
machineModelName: 'MacBookPro',
machineModelVersion: '11.5'
}
videoDecodeAcceleratorFlags: 0 },
gpuDevice:
[ { active: true, deviceId: 26657, vendorId: 4098 },
{ active: false, deviceId: 3366, vendorId: 32902 } ],
machineModelName: 'MacBookPro',
machineModelVersion: '11.5' }
```
Using `basic` should be preferred if only basic information like `vendorId` or `driverId` is needed.
@@ -1216,13 +1152,6 @@ Returns `Object`:
should restore the state from the previous session. This indicates that the
app should restore the windows that were open the last time the app was
closed. This setting is not available on [MAS builds][mas-builds].
* `executableWillLaunchAtLogin` Boolean _Windows_ - `true` if app is set to open at login and its run key is not deactivated. This differs from `openAtLogin` as it ignores the `args` option, this property will be true if the given executable would be launched at login with **any** arguments.
* `launchItems` Object[] _Windows_
* `name` String _Windows_ - name value of a registry entry.
* `path` String _Windows_ - The executable to an app that corresponds to a registry entry.
* `args` String[] _Windows_ - the command-line arguments to pass to the executable.
* `scope` String _Windows_ - one of `user` or `machine`. Indicates whether the registry entry is under `HKEY_CURRENT USER` or `HKEY_LOCAL_MACHINE`.
* `enabled` Boolean _Windows_ - `true` if the app registry key is startup approved and therefore shows as `enabled` in Task Manager and Windows settings.
### `app.setLoginItemSettings(settings)` _macOS_ _Windows_
@@ -1238,9 +1167,7 @@ Returns `Object`:
* `args` String[] (optional) _Windows_ - The command-line arguments to pass to
the executable. Defaults to an empty array. Take care to wrap paths in
quotes.
* `enabled` Boolean (optional) _Windows_ - `true` will change the startup approved registry key and `enable / disable` the App in Task Manager and Windows Settings.
Defaults to `true`.
* `name` String (optional) _Windows_ - value name to write into registry. Defaults to the app's AppUserModelId().
Set the app's login item settings.
To work with Electron's `autoUpdater` on Windows, which uses [Squirrel][Squirrel-Windows],
@@ -1295,7 +1222,7 @@ Show the app's about panel options. These options can be overridden with `app.se
* `credits` String (optional) _macOS_ _Windows_ - Credit information.
* `authors` String[] (optional) _Linux_ - List of app authors.
* `website` String (optional) _Linux_ - The app's website.
* `iconPath` String (optional) _Linux_ _Windows_ - Path to the app's icon in a JPEG or PNG file format. On Linux, will be shown as 64x64 pixels while retaining aspect ratio.
* `iconPath` String (optional) _Linux_ _Windows_ - Path to the app's icon. On Linux, will be shown as 64x64 pixels while retaining aspect ratio.
Set the about panel options. This will override the values defined in the app's `.plist` file on macOS. See the [Apple docs][about-panel-options] for more details. On Linux, values must be set in order to be shown; there are no defaults.
@@ -1356,7 +1283,7 @@ method returns false. If we fail to perform the copy, then this method will
throw an error. The message in the error should be informative and tell
you exactly what went wrong.
By default, if an app of the same name as the one being moved exists in the Applications directory and is _not_ running, the existing app will be trashed and the active app moved into its place. If it _is_ running, the pre-existing running app will assume focus and the previously active app will quit itself. This behavior can be changed by providing the optional conflict handler, where the boolean returned by the handler determines whether or not the move conflict is resolved with default behavior. i.e. returning `false` will ensure no further action is taken, returning `true` will result in the default behavior and the method continuing.
By default, if an app of the same name as the one being moved exists in the Applications directory and is _not_ running, the existing app will be trashed and the active app moved into its place. If it _is_ running, the pre-existing running app will assume focus and the the previously active app will quit itself. This behavior can be changed by providing the optional conflict handler, where the boolean returned by the handler determines whether or not the move conflict is resolved with default behavior. i.e. returning `false` will ensure no further action is taken, returning `true` will result in the default behavior and the method continuing.
For example:
@@ -1476,7 +1403,7 @@ in your app's initialization to ensure that your overridden value is used.
A `Boolean` which when `true` disables the overrides that Electron has in place
to ensure renderer processes are restarted on every navigation. The current
default value for this property is `true`.
default value for this property is `false`.
The intention is for these overrides to become disabled by default and then at
some point in the future this property will be removed. This property impacts

View File

@@ -104,7 +104,7 @@ The `autoUpdater` object has the following methods:
* `options` Object
* `url` String
* `headers` Record<String, String> (optional) _macOS_ - HTTP request headers.
* `serverType` String (optional) _macOS_ - Can be `json` or `default`, see the [Squirrel.Mac][squirrel-mac]
* `serverType` String (optional) _macOS_ - Either `json` or `default`, see the [Squirrel.Mac][squirrel-mac]
README for more information.
Sets the `url` and initialize the auto updater.

View File

@@ -28,6 +28,25 @@ view.webContents.loadURL('https://electronjs.org')
* `options` Object (optional)
* `webPreferences` Object (optional) - See [BrowserWindow](browser-window.md).
### Static Methods
#### `BrowserView.getAllViews()`
Returns `BrowserView[]` - An array of all opened BrowserViews.
#### `BrowserView.fromWebContents(webContents)`
* `webContents` [WebContents](web-contents.md)
Returns `BrowserView | null` - The BrowserView that owns the given `webContents`
or `null` if the contents are not owned by a BrowserView.
#### `BrowserView.fromId(id)`
* `id` Integer
Returns `BrowserView` - The view with the given `id`.
### Instance Properties
Objects created with `new BrowserView` have the following properties:
@@ -36,10 +55,24 @@ Objects created with `new BrowserView` have the following properties:
A [`WebContents`](web-contents.md) object owned by this view.
#### `view.id` _Experimental_
A `Integer` representing the unique ID of the view.
### Instance Methods
Objects created with `new BrowserView` have the following instance methods:
#### `view.destroy()`
Force closing the view, the `unload` and `beforeunload` events won't be emitted
for the web page. After you're done with a view, call this function in order to
free memory and other resources as soon as possible.
#### `view.isDestroyed()`
Returns `Boolean` - Whether the view is destroyed.
#### `view.setAutoResize(options)` _Experimental_
* `options` Object

View File

@@ -38,7 +38,7 @@ the window after this event will have no visual flash:
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ show: false })
let win = new BrowserWindow({ show: false })
win.once('ready-to-show', () => {
win.show()
})
@@ -60,7 +60,7 @@ immediately, and use a `backgroundColor` close to your app's background:
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ backgroundColor: '#2e2c29' })
let win = new BrowserWindow({ backgroundColor: '#2e2c29' })
win.loadURL('https://github.com')
```
@@ -74,8 +74,8 @@ By using `parent` option, you can create child windows:
```javascript
const { BrowserWindow } = require('electron')
const top = new BrowserWindow()
const child = new BrowserWindow({ parent: top })
let top = new BrowserWindow()
let child = new BrowserWindow({ parent: top })
child.show()
top.show()
```
@@ -90,7 +90,7 @@ window, you have to set both `parent` and `modal` options:
```javascript
const { BrowserWindow } = require('electron')
const child = new BrowserWindow({ parent: top, modal: true, show: false })
let child = new BrowserWindow({ parent: top, modal: true, show: false })
child.loadURL('https://github.com')
child.once('ready-to-show', () => {
child.show()
@@ -207,15 +207,11 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
* `opacity` Number (optional) - Set the initial opacity of the window, between 0.0 (fully
transparent) and 1.0 (fully opaque). This is only implemented on Windows and macOS.
* `darkTheme` Boolean (optional) - Forces using dark theme for the window, only works on
some GTK+3 desktop environments. Default is `false`.
some GTK desktop environments. Default is [`nativeTheme.shouldUseDarkColors`](native-theme.md).
* `transparent` Boolean (optional) - Makes the window [transparent](frameless-window.md#transparent-window).
Default is `false`. On Windows, does not work unless the window is frameless.
* `type` String (optional) - The type of window, default is normal window. See more about
this below.
* `visualEffectState` String (optional) - Specify how the material appearance should reflect window activity state on macOS. Must be used with the `vibrancy` property. Possible values are:
* `followWindow` - The backdrop should automatically appear active when the window is active, and inactive when it is not. This is the default.
* `active` - The backdrop should always appear active.
* `inactive` - The backdrop should always appear inactive.
* `titleBarStyle` String (optional) - The style of window title bar.
Default is `default`. Possible values are:
* `default` - Results in the standard gray opaque Mac title
@@ -275,7 +271,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
the `nodeIntegration` option and the APIs available to the preload script
are more limited. Read more about the option [here](sandbox-option.md).
* `enableRemoteModule` Boolean (optional) - Whether to enable the [`remote`](remote.md) module.
Default is `false`.
Default is `true`.
* `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
@@ -352,9 +348,6 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
You can access this context in the dev tools by selecting the
'Electron Isolated Context' entry in the combo box at the top of the
Console tab.
* `worldSafeExecuteJavaScript` Boolean (optional) - If true, values returned from `webFrame.executeJavaScript` will be sanitized to ensure JS values
can't unsafely cross between worlds when using `contextIsolation`. The default
is `false`. In Electron 12, the default will be changed to `true`. _Deprecated_
* `nativeWindowOpen` Boolean (optional) - Whether to use native
`window.open()`. Defaults to `false`. Child windows will always have node
integration disabled unless `nodeIntegrationInSubFrames` is true. **Note:** This option is currently
@@ -394,13 +387,6 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
Default is `true`.
* `enableWebSQL` Boolean (optional) - Whether to enable the [WebSQL api](https://www.w3.org/TR/webdatabase/).
Default is `true`.
* `v8CacheOptions` String (optional) - Enforces the v8 code caching policy
used by blink. Accepted values are
* `none` - Disables code caching
* `code` - Heuristic based code caching
* `bypassHeatCheck` - Bypass code caching heuristics but with lazy compilation
* `bypassHeatCheckAndEagerCompile` - Same as above except compilation is eager.
Default policy is `code`.
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
@@ -604,7 +590,7 @@ e.g. `APPCOMMAND_BROWSER_BACKWARD` is emitted as `browser-backward`.
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
let win = new BrowserWindow()
win.on('app-command', (e, cmd) => {
// Navigate the window back when the user hits their mouse back button
if (cmd === 'browser-backward' && win.webContents.canGoBack()) {
@@ -699,7 +685,7 @@ Returns `BrowserWindow | null` - The window that owns the given `browserView`. I
* `id` Integer
Returns `BrowserWindow | null` - The window with the given `id`.
Returns `BrowserWindow` - The window with the given `id`.
#### `BrowserWindow.addExtension(path)` _Deprecated_
@@ -779,7 +765,7 @@ To check if a DevTools extension is installed you can run the following:
```javascript
const { BrowserWindow } = require('electron')
const installed = 'devtron' in BrowserWindow.getDevToolsExtensions()
let installed = BrowserWindow.getDevToolsExtensions().hasOwnProperty('devtron')
console.log(installed)
```
@@ -796,7 +782,7 @@ Objects created with `new BrowserWindow` have the following properties:
```javascript
const { BrowserWindow } = require('electron')
// In this example `win` is our instance
const win = new BrowserWindow({ width: 800, height: 600 })
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://github.com')
```
@@ -1130,7 +1116,7 @@ Disable or enable the window.
#### `win.isEnabled()`
Returns `Boolean` - whether the window is enabled.
Returns Boolean - whether the window is enabled.
#### `win.setSize(width, height[, animate])`
@@ -1321,9 +1307,9 @@ a HTML-rendered toolbar. For example:
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
let win = new BrowserWindow()
const toolbarRect = document.getElementById('toolbar').getBoundingClientRect()
let toolbarRect = document.getElementById('toolbar').getBoundingClientRect()
win.setSheetOffset(toolbarRect.height)
```
@@ -1447,7 +1433,7 @@ Node's [`url.format`](https://nodejs.org/api/url.html#url_url_format_urlobject)
method:
```javascript
const url = require('url').format({
let url = require('url').format({
protocol: 'file',
slashes: true,
pathname: require('path').join(__dirname, 'index.html')
@@ -1673,12 +1659,9 @@ Sets whether the menu bar should be visible. If the menu bar is auto-hide, users
Returns `Boolean` - Whether the menu bar is visible.
#### `win.setVisibleOnAllWorkspaces(visible[, options])`
#### `win.setVisibleOnAllWorkspaces(visible)`
* `visible` Boolean
* `options` Object (optional)
* `visibleOnFullScreen` Boolean (optional) _macOS_ - Sets whether
the window should be visible above fullscreen windows
Sets whether the window should be visible on all workspaces.

View File

@@ -171,20 +171,6 @@ lowercasing. It can be called only before first write. Calling this method after
the first write will throw an error. If the passed value is not a `String`, its
`toString()` method will be called to obtain the final value.
Certain headers are restricted from being set by apps. These headers are
listed below. More information on restricted headers can be found in
[Chromium's header utils](https://source.chromium.org/chromium/chromium/src/+/master:services/network/public/cpp/header_util.cc;drc=1562cab3f1eda927938f8f4a5a91991fefde66d3;bpv=1;bpt=1;l=22).
* `Content-Length`
* `Host`
* `Trailer` or `Te`
* `Upgrade`
* `Cookie2`
* `Keep-Alive`
* `Transfer-Encoding`
Additionally, setting the `Connection` header to the value `upgrade` is also disallowed.
#### `request.getHeader(name)`
* `name` String - Specify an extra header name.

View File

@@ -36,10 +36,6 @@ for integrated authentication. Without `*` prefix the URL has to match exactly.
A comma-separated list of servers for which delegation of user credentials is required.
Without `*` prefix the URL has to match exactly.
### --disable-ntlm-v2
Disables NTLM v2 for posix platforms, no effect elsewhere.
### --disable-http-cache
Disables the disk cache for HTTP requests.
@@ -198,14 +194,6 @@ logging level for all code in the source files under a `foo/bar` directory.
This switch only works when `--enable-logging` is also passed.
### --force_high_performance_gpu
Force using discrete GPU when there are multiple GPUs available.
### --force_low_power_gpu
Force using integrated GPU when there are multiple GPUs available.
## Node.js Flags
Electron supports some of the [CLI flags][node-cli] supported by Node.js.

View File

@@ -83,4 +83,4 @@ Returns `Promise<Object>` - Resolves with an object containing the `value` and `
Get the maximum usage across processes of trace buffer as a percentage of the
full state.
[trace viewer]: https://chromium.googlesource.com/catapult/+/HEAD/tracing/README.md
[trace viewer]: https://github.com/catapult-project/catapult/blob/master/tracing

View File

@@ -156,21 +156,15 @@ parameters in a renderer process will not result in those parameters being sent
with crashes that occur in other renderer processes or in the main process.
**Note:** Parameters have limits on the length of the keys and values. Key
names must be no longer than 39 bytes, and values must be no longer than 20320
names must be no longer than 39 bytes, and values must be no longer than 127
bytes. Keys with names longer than the maximum will be silently ignored. Key
values longer than the maximum length will be truncated.
**Note:** On linux values that are longer than 127 bytes will be chunked into
multiple keys, each 127 bytes in length. E.g. `addExtraParameter('foo', 'a'.repeat(130))`
will result in two chunked keys `foo__1` and `foo__2`, the first will contain
the first 127 bytes and the second will contain the remaining 3 bytes. On
your crash reporting backend you should stitch together keys in this format.
### `crashReporter.removeExtraParameter(key)`
* `key` String - Parameter key, must be no longer than 39 bytes.
Remove an extra parameter from the current set of parameters. Future crashes
Remove a extra parameter from the current set of parameters. Future crashes
will not include this parameter.
### `crashReporter.getParameters()`

View File

@@ -9,7 +9,7 @@ runtime that allows interacting with pages and instrumenting them.
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
let win = new BrowserWindow()
try {
win.webContents.debugger.attach('1.1')
@@ -52,8 +52,6 @@ Returns:
* `method` String - Method name.
* `params` any - Event parameters defined by the 'parameters'
attribute in the remote debugging protocol.
* `sessionId` String - Unique identifier of attached debugging session,
will match the value sent from `debugger.sendCommand`.
Emitted whenever the debugging target issues an instrumentation event.
@@ -76,16 +74,11 @@ Returns `Boolean` - Whether a debugger is attached to the `webContents`.
Detaches the debugger from the `webContents`.
#### `debugger.sendCommand(method[, commandParams, sessionId])`
#### `debugger.sendCommand(method[, commandParams])`
* `method` String - Method name, should be one of the methods defined by the
[remote debugging protocol][rdp].
* `commandParams` any (optional) - JSON object with request parameters.
* `sessionId` String (optional) - send command to the target with associated
debugging session id. The initial value can be obtained by sending
[Target.attachToTarget][attachToTarget] message.
[attachToTarget]: https://chromedevtools.github.io/devtools-protocol/tot/Target/#method-attachToTarget
Returns `Promise<any>` - A promise that resolves with the response defined by
the 'returns' attribute of the command description in the remote debugging protocol

View File

@@ -269,7 +269,7 @@ Shows a message box, it will block the process until the message box is closed.
It returns the index of the clicked button.
The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.
If `browserWindow` is not shown dialog will not be attached to it. In such case it will be displayed as an independent window.
If `browserWindow` is not shown dialog will not be attached to it. In such case It will be displayed as independed window.
### `dialog.showMessageBox([browserWindow, ]options)`

View File

@@ -11,7 +11,7 @@ control the download item.
```javascript
// In the main process.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
let win = new BrowserWindow()
win.webContents.session.on('will-download', (event, item, webContents) => {
// Set the save path, making Electron not to prompt a save dialog.
item.setSavePath('/tmp/save.pdf')

View File

@@ -102,15 +102,3 @@ The following methods of `chrome.tabs` are supported:
> **Note:** In Chrome, passing `-1` as a tab ID signifies the "currently active
> tab". Since Electron has no such concept, passing `-1` as a tab ID is not
> supported and will raise an error.
### `chrome.management`
The following methods of `chrome.management` are supported:
- `chrome.management.getAll`
- `chrome.management.get`
- `chrome.management.getSelf`
- `chrome.management.getPermissionWarningsById`
- `chrome.management.getPermissionWarningsByManifest`
- `chrome.management.onEnabled`
- `chrome.management.onDisabled`

View File

@@ -15,7 +15,7 @@ To create a frameless window, you need to set `frame` to `false` in
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600, frame: false })
let win = new BrowserWindow({ width: 800, height: 600, frame: false })
win.show()
```
@@ -33,7 +33,7 @@ Results in a hidden title bar and a full size content window, yet the title bar
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'hidden' })
let win = new BrowserWindow({ titleBarStyle: 'hidden' })
win.show()
```
@@ -43,7 +43,7 @@ Results in a hidden title bar with an alternative look where the traffic light b
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'hiddenInset' })
let win = new BrowserWindow({ titleBarStyle: 'hiddenInset' })
win.show()
```
@@ -58,7 +58,7 @@ This option is only applicable for frameless windows.
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: false })
let win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: false })
win.show()
```
@@ -69,7 +69,7 @@ window transparent:
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ transparent: true, frame: false })
let win = new BrowserWindow({ transparent: true, frame: false })
win.show()
```
@@ -100,7 +100,7 @@ API:
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
let win = new BrowserWindow()
win.setIgnoreMouseEvents(true)
```
@@ -112,8 +112,8 @@ optional parameter can be used to forward mouse move messages to the web page,
allowing events such as `mouseleave` to be emitted:
```javascript
const win = require('electron').remote.getCurrentWindow()
const el = document.getElementById('clickThroughElement')
let win = require('electron').remote.getCurrentWindow()
let el = document.getElementById('clickThroughElement')
el.addEventListener('mouseenter', () => {
win.setIgnoreMouseEvents(true, { forward: true })
})

View File

@@ -148,4 +148,4 @@ found in the [`ipc-main-invoke-event`](structures/ipc-main-invoke-event.md)
structure docs.
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
[web-contents-send]: web-contents.md#contentssendchannel-args
[web-contents-send]: web-contents.md#contentssendchannel-arg1-arg2-

View File

@@ -108,7 +108,7 @@ ipcMain.handle('some-name', async (event, someArgument) => {
If you need to transfer a [`MessagePort`][] to the main process, use [`ipcRenderer.postMessage`](#ipcrendererpostmessagechannel-message-transfer).
If you do not need a response to the message, consider using [`ipcRenderer.send`](#ipcrenderersendchannel-args).
If you do not need a respons to the message, consider using [`ipcRenderer.send`](#ipcrenderersendchannel-args).
### `ipcRenderer.sendSync(channel, ...args)`

View File

@@ -12,7 +12,7 @@ See [`Menu`](menu.md) for examples.
* `click` Function (optional) - Will be called with
`click(menuItem, browserWindow, event)` when the menu item is clicked.
* `menuItem` MenuItem
* `browserWindow` [BrowserWindow](browser-window.md) | undefined - This will not be defined if no window is open.
* `browserWindow` [BrowserWindow](browser-window.md)
* `event` [KeyboardEvent](structures/keyboard-event.md)
* `role` String (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
`click` property will be ignored. See [roles](#roles).
@@ -69,7 +69,6 @@ a `type`.
The `role` property can have following values:
* `undo`
* `about` - Trigger a native about panel (custom message box on Window, which does not provide its own).
* `redo`
* `cut`
* `copy`
@@ -95,6 +94,7 @@ The `role` property can have following values:
The following additional roles are available on _macOS_:
* `appMenu` - Whole default "App" menu (About, Services, etc.)
* `about` - Map to the `orderFrontStandardAboutPanel` action.
* `hide` - Map to the `hide` action.
* `hideOthers` - Map to the `hideOtherApplications` action.
* `unhide` - Map to the `unhideAllApplications` action.

View File

@@ -96,7 +96,7 @@ Appends the `menuItem` to the menu.
* `id` String
Returns `MenuItem | null` the item with the specified `id`
Returns `MenuItem` the item with the specified `id`
#### `menu.insert(pos, menuItem)`
@@ -195,8 +195,8 @@ const template = [
{
label: 'Speech',
submenu: [
{ role: 'startSpeaking' },
{ role: 'stopSpeaking' }
{ role: 'startspeaking' },
{ role: 'stopspeaking' }
]
}
] : [
@@ -211,12 +211,12 @@ const template = [
label: 'View',
submenu: [
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ role: 'forcereload' },
{ role: 'toggledevtools' },
{ type: 'separator' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ role: 'resetzoom' },
{ role: 'zoomin' },
{ role: 'zoomout' },
{ type: 'separator' },
{ role: 'togglefullscreen' }
]

View File

@@ -1,6 +1,6 @@
## Modernization
The Electron team is currently undergoing an initiative to modernize our API in a few concrete ways. These include: updating our modules to use idiomatic JS properties instead of separate `getPropertyX` and `setpropertyX`, converting callbacks to promises, and removing some other anti-patterns present in our APIs. The current status of the Promise initiative can be tracked in the [promisification](promisification.md) tracking file.
The Electron team is currently undergoing an initiative to modernize our API in a few concrete ways. These include: updating our modules to use idiomatic JS properties instead of separate `getPropertyX` and `setpropertyX`, converting callbacks to promises, and removing some other anti-patterns present in our APIs. The current status of the Promise intiative can be tracked in the [promisification](promisification.md) tracking file.
As we work to perform these updates, we seek to create the least disruptive amount of change at any given time, so as many changes as possible will be introduced in a backward compatible manner and deprecated after enough time has passed to give users a chance to upgrade their API calls.

View File

@@ -119,13 +119,6 @@ Returns `NativeImage`
Creates an empty `NativeImage` instance.
### `nativeImage.createThumbnailFromPath(path, maxSize)` _macOS_ _Windows_
* `path` String - path to a file that we intend to construct a thumbnail out of.
* `maxSize` [Size](structures/size.md) - the maximum width and height (positive numbers) the thumbnail returned can be. The Windows implementation will ignore `maxSize.height` and scale the height according to `maxSize.width`.
Returns `Promise<NativeImage>` - fulfilled with the file's thumbnail preview image, which is a [NativeImage](native-image.md).
### `nativeImage.createFromPath(path)`
* `path` String

View File

@@ -58,7 +58,7 @@ Your application should then always use `shouldUseDarkColors` to determine what
### `nativeTheme.shouldUseHighContrastColors` _macOS_ _Windows_ _Readonly_
A `Boolean` for if the OS / Chromium currently has high-contrast mode enabled
or is being instructed to show a high-contrast UI.
or is being instructed to show a high-constrast UI.
### `nativeTheme.shouldUseInvertedColorScheme` _macOS_ _Windows_ _Readonly_

View File

@@ -8,19 +8,19 @@ Process: [Main](../glossary.md#main-process)
The `powerMonitor` module emits the following events:
### Event: 'suspend' _macOS_ _Windows_
### Event: 'suspend'
Emitted when the system is suspending.
### Event: 'resume' _macOS_ _Windows_
### Event: 'resume'
Emitted when system is resuming.
### Event: 'on-ac' _macOS_ _Windows_
### Event: 'on-ac' _Windows_
Emitted when the system changes to AC power.
### Event: 'on-battery' _macOS_ _Windows_
### Event: 'on-battery' _Windows_
Emitted when system changes to battery power.

309
docs/api/protocol-ns.md Normal file
View File

@@ -0,0 +1,309 @@
# protocol (NetworkService) (Draft)
This document describes the new protocol APIs based on the [NetworkService](https://www.chromium.org/servicification).
We don't currently have an estimate of when we will enable the `NetworkService` by
default in Electron, but as Chromium is already removing non-`NetworkService`
code, we will probably switch before Electron 10.
The content of this document should be moved to `protocol.md` after we have
enabled the `NetworkService` by default in Electron.
> Register a custom protocol and intercept existing protocol requests.
Process: [Main](../glossary.md#main-process)
An example of implementing a protocol that has the same effect as the
`file://` protocol:
```javascript
const { app, protocol } = require('electron')
const path = require('path')
app.whenReady().then(() => {
protocol.registerFileProtocol('atom', (request, callback) => {
const url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
})
})
```
**Note:** All methods unless specified can only be used after the `ready` event
of the `app` module gets emitted.
## Using `protocol` with a custom `partition` or `session`
A protocol is registered to a specific Electron [`session`](./session.md)
object. If you don't specify a session, then your `protocol` will be applied to
the default session that Electron uses. However, if you define a `partition` or
`session` on your `browserWindow`'s `webPreferences`, then that window will use
a different session and your custom protocol will not work if you just use
`electron.protocol.XXX`.
To have your custom protocol work in combination with a custom session, you need
to register it to that session explicitly.
```javascript
const { session, app, protocol } = require('electron')
const path = require('path')
app.whenReady().then(() => {
const partition = 'persist:example'
const ses = session.fromPartition(partition)
ses.protocol.registerFileProtocol('atom', (request, callback) => {
const url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
})
mainWindow = new BrowserWindow({ webPreferences: { partition } })
})
```
## Methods
The `protocol` module has the following methods:
### `protocol.registerSchemesAsPrivileged(customSchemes)`
* `customSchemes` [CustomScheme[]](structures/custom-scheme.md)
**Note:** This method can only be used before the `ready` event of the `app`
module gets emitted and can be called only once.
Registers the `scheme` as standard, secure, bypasses content security policy for
resources, allows registering ServiceWorker and supports fetch API. Specify a
privilege with the value of `true` to enable the capability.
An example of registering a privileged scheme, that bypasses Content Security
Policy:
```javascript
const { protocol } = require('electron')
protocol.registerSchemesAsPrivileged([
{ scheme: 'foo', privileges: { bypassCSP: true } }
])
```
A standard scheme adheres to what RFC 3986 calls [generic URI
syntax](https://tools.ietf.org/html/rfc3986#section-3). For example `http` and
`https` are standard schemes, while `file` is not.
Registering a scheme as standard allows relative and absolute resources to
be resolved correctly when served. Otherwise the scheme will behave like the
`file` protocol, but without the ability to resolve relative URLs.
For example when you load following page with custom protocol without
registering it as standard scheme, the image will not be loaded because
non-standard schemes can not recognize relative URLs:
```html
<body>
<img src='test.png'>
</body>
```
Registering a scheme as standard will allow access to files through the
[FileSystem API][file-system-api]. Otherwise the renderer will throw a security
error for the scheme.
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB,
cookies) are disabled for non standard schemes. So in general if you want to
register a custom protocol to replace the `http` protocol, you have to register
it as a standard scheme.
### `protocol.registerFileProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Registers a protocol of `scheme` that will send a file as the response. The
`handler` will be called with `request` and `callback` where `request` is
an incoming request for the `scheme`.
To handle the `request`, the `callback` should be called with either the file's
path or an object that has a `path` property, e.g. `callback(filePath)` or
`callback({ path: filePath })`. The `filePath` must be an absolute path.
By default the `scheme` is treated like `http:`, which is parsed differently
from protocols that follow the "generic URI syntax" like `file:`.
### `protocol.registerBufferProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
Registers a protocol of `scheme` that will send a `Buffer` as a response.
The usage is the same with `registerFileProtocol`, except that the `callback`
should be called with either a `Buffer` object or an object that has the `data`
property.
Example:
```javascript
protocol.registerBufferProtocol('atom', (request, callback) => {
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
})
```
### `protocol.registerStringProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Registers a protocol of `scheme` that will send a `String` as a response.
The usage is the same with `registerFileProtocol`, except that the `callback`
should be called with either a `String` or an object that has the `data`
property.
### `protocol.registerHttpProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` ProtocolResponse
Registers a protocol of `scheme` that will send an HTTP request as a response.
The usage is the same with `registerFileProtocol`, except that the `callback`
should be called with an object that has the `url` property.
### `protocol.registerStreamProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
Registers a protocol of `scheme` that will send a stream as a response.
The usage is the same with `registerFileProtocol`, except that the
`callback` should be called with either a [`ReadableStream`](https://nodejs.org/api/stream.html#stream_class_stream_readable) object or an object that
has the `data` property.
Example:
```javascript
const { protocol } = require('electron')
const { PassThrough } = require('stream')
function createStream (text) {
const rv = new PassThrough() // PassThrough is also a Readable stream
rv.push(text)
rv.push(null)
return rv
}
protocol.registerStreamProtocol('atom', (request, callback) => {
callback({
statusCode: 200,
headers: {
'content-type': 'text/html'
},
data: createStream('<h5>Response</h5>')
})
})
```
It is possible to pass any object that implements the readable stream API (emits
`data`/`end`/`error` events). For example, here's how a file could be returned:
```javascript
protocol.registerStreamProtocol('atom', (request, callback) => {
callback(fs.createReadStream('index.html'))
})
```
### `protocol.unregisterProtocol(scheme)`
* `scheme` String
Unregisters the custom protocol of `scheme`.
### `protocol.isProtocolRegistered(scheme)`
* `scheme` String
Returns `Boolean` - Whether `scheme` is already registered.
### `protocol.interceptFileProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a file as a response.
### `protocol.interceptStringProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a `String` as a response.
### `protocol.interceptBufferProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a `Buffer` as a response.
### `protocol.interceptHttpProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` ProtocolResponse
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a new HTTP request as a response.
### `protocol.interceptStreamProtocol(scheme, handler)`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `callback` Function
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
Same as `protocol.registerStreamProtocol`, except that it replaces an existing
protocol handler.
### `protocol.uninterceptProtocol(scheme)`
* `scheme` String
Remove the interceptor installed for `scheme` and restore its original handler.
### `protocol.isProtocolIntercepted(scheme)`
* `scheme` String
Returns `Boolean` - Whether `scheme` is already intercepted.
[file-system-api]: https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem

View File

@@ -15,6 +15,8 @@ app.whenReady().then(() => {
protocol.registerFileProtocol('atom', (request, callback) => {
const url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
}, (error) => {
if (error) console.error('Failed to register protocol')
})
})
```
@@ -24,15 +26,9 @@ of the `app` module gets emitted.
## Using `protocol` with a custom `partition` or `session`
A protocol is registered to a specific Electron [`session`](./session.md)
object. If you don't specify a session, then your `protocol` will be applied to
the default session that Electron uses. However, if you define a `partition` or
`session` on your `browserWindow`'s `webPreferences`, then that window will use
a different session and your custom protocol will not work if you just use
`electron.protocol.XXX`.
A protocol is registered to a specific Electron [`session`](./session.md) object. If you don't specify a session, then your `protocol` will be applied to the default session that Electron uses. However, if you define a `partition` or `session` on your `browserWindow`'s `webPreferences`, then that window will use a different session and your custom protocol will not work if you just use `electron.protocol.XXX`.
To have your custom protocol work in combination with a custom session, you need
to register it to that session explicitly.
To have your custom protocol work in combination with a custom session, you need to register it to that session explicitly.
```javascript
const { session, app, protocol } = require('electron')
@@ -45,9 +41,17 @@ app.whenReady().then(() => {
ses.protocol.registerFileProtocol('atom', (request, callback) => {
const url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
}, (error) => {
if (error) console.error('Failed to register protocol')
})
mainWindow = new BrowserWindow({ webPreferences: { partition } })
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
partition: partition
}
})
})
```
@@ -59,15 +63,15 @@ The `protocol` module has the following methods:
* `customSchemes` [CustomScheme[]](structures/custom-scheme.md)
**Note:** This method can only be used before the `ready` event of the `app`
module gets emitted and can be called only once.
Registers the `scheme` as standard, secure, bypasses content security policy for
resources, allows registering ServiceWorker, supports fetch API, and streaming
video/audio. Specify a privilege with the value of `true` to enable the capability.
Registers the `scheme` as standard, secure, bypasses content security policy for resources,
allows registering ServiceWorker and supports fetch API.
An example of registering a privileged scheme, that bypasses Content Security
Policy:
Specify a privilege with the value of `true` to enable the capability.
An example of registering a privileged scheme, with bypassing Content Security Policy:
```javascript
const { protocol } = require('electron')
@@ -80,7 +84,7 @@ A standard scheme adheres to what RFC 3986 calls [generic URI
syntax](https://tools.ietf.org/html/rfc3986#section-3). For example `http` and
`https` are standard schemes, while `file` is not.
Registering a scheme as standard allows relative and absolute resources to
Registering a scheme as standard, will allow relative and absolute resources to
be resolved correctly when served. Otherwise the scheme will behave like the
`file` protocol, but without the ability to resolve relative URLs.
@@ -98,107 +102,168 @@ Registering a scheme as standard will allow access to files through the
[FileSystem API][file-system-api]. Otherwise the renderer will throw a security
error for the scheme.
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB,
cookies) are disabled for non standard schemes. So in general if you want to
register a custom protocol to replace the `http` protocol, you have to register
it as a standard scheme.
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB, cookies)
are disabled for non standard schemes. So in general if you want to register a
custom protocol to replace the `http` protocol, you have to register it as a standard scheme.
Protocols that use streams (http and stream protocols) should set `stream: true`.
The `<video>` and `<audio>` HTML elements expect protocols to buffer their
responses by default. The `stream` flag configures those elements to correctly
expect streaming responses.
`protocol.registerSchemesAsPrivileged` can be used to replicate the functionality of the previous `protocol.registerStandardSchemes`, `webFrame.registerURLSchemeAs*` and `protocol.registerServiceWorkerSchemes` functions that existed prior to Electron 5.0.0, for example:
### `protocol.registerFileProtocol(scheme, handler)`
**before (<= v4.x)**
```javascript
// Main
protocol.registerStandardSchemes(['scheme1', 'scheme2'], { secure: true })
// Renderer
webFrame.registerURLSchemeAsPrivileged('scheme1', { secure: true })
webFrame.registerURLSchemeAsPrivileged('scheme2', { secure: true })
```
**after (>= v5.x)**
```javascript
protocol.registerSchemesAsPrivileged([
{ scheme: 'scheme1', privileges: { standard: true, secure: true } },
{ scheme: 'scheme2', privileges: { standard: true, secure: true } }
])
```
### `protocol.registerFileProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `callback` Function
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
* `filePath` String | [FilePathWithHeaders](structures/file-path-with-headers.md) (optional)
* `completion` Function (optional)
* `error` Error
Returns `Boolean` - Whether the protocol was successfully registered
Registers a protocol of `scheme` that will send a file as the response. The
`handler` will be called with `request` and `callback` where `request` is
an incoming request for the `scheme`.
Registers a protocol of `scheme` that will send the file as a response. The
`handler` will be called with `handler(request, callback)` when a `request` is
going to be created with `scheme`. `completion` will be called with
`completion(null)` when `scheme` is successfully registered or
`completion(error)` when failed.
To handle the `request`, the `callback` should be called with either the file's
path or an object that has a `path` property, e.g. `callback(filePath)` or
`callback({ path: filePath })`. The `filePath` must be an absolute path.
`callback({ path: filePath })`. The object may also have a `headers` property
which gives a map of headers to values for the response headers, e.g.
`callback({ path: filePath, headers: {"Content-Security-Policy": "default-src 'none'"]})`.
When `callback` is called with nothing, a number, or an object that has an
`error` property, the `request` will fail with the `error` number you
specified. For the available error numbers you can use, please see the
[net error list][net-error].
By default the `scheme` is treated like `http:`, which is parsed differently
from protocols that follow the "generic URI syntax" like `file:`.
than protocols that follow the "generic URI syntax" like `file:`.
### `protocol.registerBufferProtocol(scheme, handler)`
### `protocol.registerBufferProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `callback` Function
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
Returns `Boolean` - Whether the protocol was successfully registered
* `buffer` (Buffer | [MimeTypedBuffer](structures/mime-typed-buffer.md)) (optional)
* `completion` Function (optional)
* `error` Error
Registers a protocol of `scheme` that will send a `Buffer` as a response.
The usage is the same with `registerFileProtocol`, except that the `callback`
should be called with either a `Buffer` object or an object that has the `data`
property.
should be called with either a `Buffer` object or an object that has the `data`,
`mimeType`, and `charset` properties.
Example:
```javascript
const { protocol } = require('electron')
protocol.registerBufferProtocol('atom', (request, callback) => {
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
}, (error) => {
if (error) console.error('Failed to register protocol')
})
```
### `protocol.registerStringProtocol(scheme, handler)`
### `protocol.registerStringProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `callback` Function
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Returns `Boolean` - Whether the protocol was successfully registered
* `data` (String | [StringProtocolResponse](structures/string-protocol-response.md)) (optional)
* `completion` Function (optional)
* `error` Error
Registers a protocol of `scheme` that will send a `String` as a response.
The usage is the same with `registerFileProtocol`, except that the `callback`
should be called with either a `String` or an object that has the `data`
property.
should be called with either a `String` or an object that has the `data`,
`mimeType`, and `charset` properties.
### `protocol.registerHttpProtocol(scheme, handler)`
### `protocol.registerHttpProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `callback` Function
* `response` ProtocolResponse
Returns `Boolean` - Whether the protocol was successfully registered
* `redirectRequest` Object
* `url` String
* `method` String (optional)
* `session` Session | null (optional)
* `uploadData` [ProtocolResponseUploadData](structures/protocol-response-upload-data.md) (optional)
* `completion` Function (optional)
* `error` Error
Registers a protocol of `scheme` that will send an HTTP request as a response.
The usage is the same with `registerFileProtocol`, except that the `callback`
should be called with an object that has the `url` property.
should be called with a `redirectRequest` object that has the `url`, `method`,
`referrer`, `uploadData` and `session` properties.
### `protocol.registerStreamProtocol(scheme, handler)`
By default the HTTP request will reuse the current session. If you want the
request to have a different session you should set `session` to `null`.
For POST requests the `uploadData` object must be provided.
### `protocol.registerStreamProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `callback` Function
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
* `stream` (ReadableStream | [StreamProtocolResponse](structures/stream-protocol-response.md)) (optional)
* `completion` Function (optional)
* `error` Error
Returns `Boolean` - Whether the protocol was successfully registered
Registers a protocol of `scheme` that will send a `Readable` as a response.
Registers a protocol of `scheme` that will send a stream as a response.
The usage is the same with `registerFileProtocol`, except that the
`callback` should be called with either a [`ReadableStream`](https://nodejs.org/api/stream.html#stream_class_stream_readable) object or an object that
has the `data` property.
The usage is similar to the other `register{Any}Protocol`, except that the
`callback` should be called with either a `Readable` object or an object that
has the `data`, `statusCode`, and `headers` properties.
Example:
@@ -221,6 +286,8 @@ protocol.registerStreamProtocol('atom', (request, callback) => {
},
data: createStream('<h5>Response</h5>')
})
}, (error) => {
if (error) console.error('Failed to register protocol')
})
```
@@ -228,102 +295,132 @@ It is possible to pass any object that implements the readable stream API (emits
`data`/`end`/`error` events). For example, here's how a file could be returned:
```javascript
const { protocol } = require('electron')
const fs = require('fs')
protocol.registerStreamProtocol('atom', (request, callback) => {
callback(fs.createReadStream('index.html'))
}, (error) => {
if (error) console.error('Failed to register protocol')
})
```
### `protocol.unregisterProtocol(scheme)`
### `protocol.unregisterProtocol(scheme[, completion])`
* `scheme` String
Returns `Boolean` - Whether the protocol was successfully unregistered
* `completion` Function (optional)
* `error` Error
Unregisters the custom protocol of `scheme`.
### `protocol.isProtocolRegistered(scheme)`
### `protocol.isProtocolHandled(scheme)`
* `scheme` String
Returns `Boolean` - Whether `scheme` is already registered.
Returns `Promise<Boolean>` - fulfilled with a boolean that indicates whether there is
already a handler for `scheme`.
### `protocol.interceptFileProtocol(scheme, handler)`
### `protocol.interceptFileProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `callback` Function
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Returns `Boolean` - Whether the protocol was successfully intercepted
* `filePath` String
* `completion` Function (optional)
* `error` Error
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a file as a response.
### `protocol.interceptStringProtocol(scheme, handler)`
### `protocol.interceptStringProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `callback` Function
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
Returns `Boolean` - Whether the protocol was successfully intercepted
* `data` (String | [StringProtocolResponse](structures/string-protocol-response.md)) (optional)
* `completion` Function (optional)
* `error` Error
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a `String` as a response.
### `protocol.interceptBufferProtocol(scheme, handler)`
### `protocol.interceptBufferProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `callback` Function
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
Returns `Boolean` - Whether the protocol was successfully intercepted
* `buffer` Buffer (optional)
* `completion` Function (optional)
* `error` Error
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a `Buffer` as a response.
### `protocol.interceptHttpProtocol(scheme, handler)`
### `protocol.interceptHttpProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `callback` Function
* `response` [ProtocolResponse](structures/protocol-response.md)
Returns `Boolean` - Whether the protocol was successfully intercepted
* `redirectRequest` Object
* `url` String
* `method` String (optional)
* `session` Session | null (optional)
* `uploadData` [ProtocolResponseUploadData](structures/protocol-response-upload-data.md) (optional)
* `completion` Function (optional)
* `error` Error
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a new HTTP request as a response.
### `protocol.interceptStreamProtocol(scheme, handler)`
### `protocol.interceptStreamProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `request` ProtocolRequest
* `request` Object
* `url` String
* `headers` Record<String, String>
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](structures/upload-data.md)
* `callback` Function
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
Returns `Boolean` - Whether the protocol was successfully intercepted
* `stream` (ReadableStream | [StreamProtocolResponse](structures/stream-protocol-response.md)) (optional)
* `completion` Function (optional)
* `error` Error
Same as `protocol.registerStreamProtocol`, except that it replaces an existing
protocol handler.
### `protocol.uninterceptProtocol(scheme)`
### `protocol.uninterceptProtocol(scheme[, completion])`
* `scheme` String
Returns `Boolean` - Whether the protocol was successfully unintercepted
* `completion` Function (optional)
* `error` Error
Remove the interceptor installed for `scheme` and restore its original handler.
### `protocol.isProtocolIntercepted(scheme)`
* `scheme` String
Returns `Boolean` - Whether `scheme` is already intercepted.
[net-error]: https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h
[file-system-api]: https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem

View File

@@ -17,7 +17,7 @@ renderer process:
```javascript
const { BrowserWindow } = require('electron').remote
const win = new BrowserWindow({ width: 800, height: 600 })
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://github.com')
```

View File

@@ -33,8 +33,8 @@ const { app, BrowserWindow, screen } = require('electron')
let win
app.whenReady().then(() => {
const displays = screen.getAllDisplays()
const externalDisplay = displays.find((display) => {
let displays = screen.getAllDisplays()
let externalDisplay = displays.find((display) => {
return display.bounds.x !== 0 || display.bounds.y !== 0
})

View File

@@ -39,7 +39,7 @@ Returns:
* `message` String - The actual console message
* `versionId` Number - The version ID of the service worker that sent the log message
* `source` String - The type of source for this message. Can be `javascript`, `xml`, `network`, `console-api`, `storage`, `app-cache`, `rendering`, `security`, `deprecation`, `worker`, `violation`, `intervention`, `recommendation` or `other`.
* `level` Number - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
* `level` Number - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
* `sourceUrl` String - The URL the message came from
* `lineNumber` Number - The line number of the source that triggered this console message

View File

@@ -12,7 +12,7 @@ property of [`WebContents`](web-contents.md), or from the `session` module.
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600 })
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')
const ses = win.webContents.session
@@ -332,7 +332,7 @@ verify proc.
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
let win = new BrowserWindow()
win.webContents.session.setCertificateVerifyProc((request, callback) => {
const { hostname } = request
@@ -348,16 +348,8 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
* `handler` Function | null
* `webContents` [WebContents](web-contents.md) - WebContents requesting the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin.
* `permission` String - The type of requested permission.
* `media` - Request access to media devices such as camera, microphone and speakers.
* `mediaKeySystem` - Request access to DRM protected content.
* `geolocation` - Request access to user's current location.
* `notifications` - Request notification creation and the ability to display them in the user's system tray.
* `midi` - Request MIDI access in the `webmidi` API.
* `midiSysex` - Request the use of system exclusive messages in the `webmidi` API.
* `pointerLock` - Request to directly interpret mouse movements as an input method. Click [here](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API) to know more.
* `fullscreen` - Request for the app to enter fullscreen mode.
* `openExternal` - Request to open links in external applications.
* `permission` String - Enum of 'media', 'geolocation', 'notifications', 'midiSysex',
'pointerLock', 'fullscreen', 'openExternal'.
* `callback` Function
* `permissionGranted` Boolean - Allow or deny the permission.
* `details` Object - Some properties are only available on certain permission types.
@@ -389,7 +381,7 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
* `permission` String - Enum of 'media'.
* `requestingOrigin` String - The origin URL of the permission check
* `details` Object - Some properties are only available on certain permission types.
* `securityOrigin` String - The security origin of the `media` check.
* `securityOrigin` String - The security orign of the `media` check.
* `mediaType` String - The type of media access being requested, can be `video`,
`audio` or `unknown`
* `requestingUrl` String - The last URL the requesting frame loaded
@@ -526,7 +518,7 @@ Returns `String[]` - An array of language codes the spellchecker is enabled for.
will fallback to using `en-US`. By default on launch if this setting is an empty list Electron will try to populate this
setting with the current OS locale. This setting is persisted across restarts.
**Note:** On macOS the OS spellchecker is used and has its own list of languages. This API is a no-op on macOS.
**Note:** On macOS the OS spellchecker is used and has it's own list of languages. This API is a no-op on macOS.
#### `ses.setSpellCheckerDictionaryDownloadURL(url)`
@@ -663,7 +655,7 @@ const path = require('path')
app.whenReady().then(() => {
const protocol = session.fromPartition('some-partition').protocol
protocol.registerFileProtocol('atom', (request, callback) => {
const url = request.url.substr(7)
let url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
}, (error) => {
if (error) console.error('Failed to register protocol')

View File

@@ -30,7 +30,7 @@ Show the given file in a file manager. If possible, select the file.
* `path` String
Returns `Promise<String>` - Resolves with a string containing the error message corresponding to the failure if a failure occurred, otherwise "".
Returns `Promise<String>` - Resolves with an string containing the error message corresponding to the failure if a failure occurred, otherwise "".
Open the given file in the desktop's default manner.

View File

@@ -8,4 +8,3 @@
* `allowServiceWorkers` Boolean (optional) - Default false.
* `supportFetchAPI` Boolean (optional) - Default false.
* `corsEnabled` Boolean (optional) - Default false.
* `stream` Boolean (optional) - Default false.

View File

@@ -19,5 +19,5 @@
available.
* `appIcon` [NativeImage](../native-image.md) - An icon image of the
application that owns the window or null if the source has a type screen.
The size of the icon is not known in advance and depends on what
The size of the icon is not known in advance and depends on what the
the application provides.

View File

@@ -1,4 +1,4 @@
# KeyboardEvent Object
# KeyboardEvent Object extends `Event`
* `ctrlKey` Boolean (optional) - whether the Control key was used in an accelerator to trigger the Event
* `metaKey` Boolean (optional) - whether a meta key was used in an accelerator to trigger the Event

View File

@@ -7,7 +7,7 @@
* `isDefault` Boolean - whether or not a given printer is set as the default printer on the OS.
* `options` Object - an object containing a variable number of platform-specific printer information.
The number represented by `status` means different things on different platforms: on Windows its potential values can be found [here](https://docs.microsoft.com/en-us/windows/win32/printdocs/printer-info-2), and on Linux and macOS they can be found [here](https://www.cups.org/doc/cupspm.html).
The number represented by `status` means different things on different platforms: on Windows it's potential values can be found [here](https://docs.microsoft.com/en-us/windows/win32/printdocs/printer-info-2), and on Linux and macOS they can be found [here](https://www.cups.org/doc/cupspm.html).
## Example

View File

@@ -11,8 +11,6 @@
* `Pepper Plugin`
* `Pepper Plugin Broker`
* `Unknown`
* `name` String (optional) - The name of the process. i.e. for plugins it might be Flash.
Examples for utility: `Audio Service`, `Content Decryption Module Service`, `Network Service`, `Video Capture`, etc.
* `cpu` [CPUUsage](cpu-usage.md) - CPU usage of the process.
* `creationTime` Number - Creation time for this process.
The time is represented as number of milliseconds since epoch.

View File

@@ -7,5 +7,4 @@
* `contentLengths` Number[] - The total size of the content, in bytes.
* `price` Number - The cost of the product in the local currency.
* `formattedPrice` String - The locale formatted price of the product.
* `currencyCode` String - 3 character code presenting a product's currency based on the ISO 4217 standard.
* `isDownloadable` Boolean - A Boolean value that indicates whether the App Store has downloadable content for this product. `true` if at least one file has been associated with the product.

View File

@@ -4,4 +4,3 @@
* `referrer` String
* `method` String
* `uploadData` [UploadData[]](upload-data.md) (optional)
* `headers` Record<String, String>

View File

@@ -0,0 +1,5 @@
# StreamProtocolResponse Object
* `statusCode` Number (optional) - The HTTP response code.
* `headers` Record<String, String | String[]> (optional) - An object containing the response headers.
* `data` ReadableStream | null - A Node.js readable stream representing the response body.

View File

@@ -0,0 +1,5 @@
# StringProtocolResponse Object
* `mimeType` String (optional) - MIME type of the response.
* `charset` String (optional) - Charset of the response.
* `data` String | null - A string representing the response body.

View File

@@ -6,7 +6,7 @@
* `trace_buffer_size_in_events` number (optional) - maximum size of the trace
recording buffer in events.
* `enable_argument_filter` boolean (optional) - if true, filter event data
according to a specific list of events that have been manually vetted to not
according to a whitelist of events that have been manually vetted to not
include any PII. See [the implementation in
Chromium][trace_event_args_whitelist.cc] for specifics.
* `included_categories` String[] (optional) - a list of tracing categories to
@@ -41,7 +41,7 @@ An example TraceConfig that roughly matches what Chrome DevTools records:
'disabled-by-default-v8.cpu_profiler',
'disabled-by-default-v8.cpu_profiler.hires'
],
excluded_categories: ['*']
excluded_categories: [ '*' ]
}
```

View File

@@ -209,7 +209,7 @@ not (transparent windows won't work correctly when DWM composition is disabled):
```javascript
const { BrowserWindow, systemPreferences } = require('electron')
const browserOptions = { width: 1000, height: 800 }
let browserOptions = { width: 1000, height: 800 }
// Make the window transparent only if the platform supports it.
if (process.platform !== 'win32' || systemPreferences.isAeroGlassEnabled()) {
@@ -218,7 +218,7 @@ if (process.platform !== 'win32' || systemPreferences.isAeroGlassEnabled()) {
}
// Create the window.
const win = new BrowserWindow(browserOptions)
let win = new BrowserWindow(browserOptions)
// Navigate.
if (browserOptions.transparent) {
@@ -406,7 +406,7 @@ systemPreferences.promptTouchID('To get consent for a Security-Gated Thing').the
})
```
This API itself will not protect your user data; rather, it is a mechanism to allow you to do so. Native apps will need to set [Access Control Constants](https://developer.apple.com/documentation/security/secaccesscontrolcreateflags?language=objc) like [`kSecAccessControlUserPresence`](https://developer.apple.com/documentation/security/secaccesscontrolcreateflags/ksecaccesscontroluserpresence?language=objc) on their keychain entry so that reading it would auto-prompt for Touch ID biometric consent. This could be done with [`node-keytar`](https://github.com/atom/node-keytar), such that one would store an encryption key with `node-keytar` and only fetch it if `promptTouchID()` resolves.
This API itself will not protect your user data; rather, it is a mechanism to allow you to do so. Native apps will need to set [Access Control Constants](https://developer.apple.com/documentation/security/secaccesscontrolcreateflags?language=objc) like [`kSecAccessControlUserPresence`](https://developer.apple.com/documentation/security/secaccesscontrolcreateflags/ksecaccesscontroluserpresence?language=objc) on the their keychain entry so that reading it would auto-prompt for Touch ID biometric consent. This could be done with [`node-keytar`](https://github.com/atom/node-keytar), such that one would store an encryption key with `node-keytar` and only fetch it if `promptTouchID()` resolves.
**NOTE:** This API will return a rejected Promise on macOS systems older than Sierra 10.12.2.
@@ -416,7 +416,7 @@ This API itself will not protect your user data; rather, it is a mechanism to al
Returns `Boolean` - `true` if the current process is a trusted accessibility client and `false` if it is not.
### `systemPreferences.getMediaAccessStatus(mediaType)` _Windows_ _macOS_
### `systemPreferences.getMediaAccessStatus(mediaType)` _macOS_
* `mediaType` String - Can be `microphone`, `camera` or `screen`.
@@ -426,9 +426,6 @@ This user consent was not required on macOS 10.13 High Sierra or lower so this m
macOS 10.14 Mojave or higher requires consent for `microphone` and `camera` access.
macOS 10.15 Catalina or higher requires consent for `screen` access.
Windows 10 has a global setting controlling `microphone` and `camera` access for all win32 applications.
It will always return `granted` for `screen` and for all media types on older versions of Windows.
### `systemPreferences.askForMediaAccess(mediaType)` _macOS_
* `mediaType` String - the type of media being requested; can be `microphone`, `camera`.

View File

@@ -41,10 +41,6 @@ the button in the touch bar.
A `NativeImage` representing the button's current icon. Changing this value immediately updates the button
in the touch bar.
#### `touchBarButton.iconPosition`
A `String` - Can be `left`, `right` or `overlay`. Defaults to `overlay`.
#### `touchBarButton.enabled`
A `Boolean` representing whether the button is in an enabled state.

View File

@@ -49,7 +49,3 @@ updates the control in the touch bar. Updating deep properties inside this array
An `Integer` representing the currently selected segment. Changing this value immediately updates the control
in the touch bar. User interaction with the touch bar will update this value automatically.
#### `touchBarSegmentedControl.mode`
A `String` representing the current selection mode of the control. Can be `single`, `multiple` or `buttons`.

View File

@@ -11,11 +11,3 @@ Process: [Main](../tutorial/application-architecture.md#main-and-renderer-proces
* `small` - Small space between items. Maps to `NSTouchBarItemIdentifierFixedSpaceSmall`. This is the default.
* `large` - Large space between items. Maps to `NSTouchBarItemIdentifierFixedSpaceLarge`.
* `flexible` - Take up all available space. Maps to `NSTouchBarItemIdentifierFlexibleSpace`.
### Instance Properties
The following properties are available on instances of `TouchBarSpacer`:
#### `touchBarSpacer.size`
A `String` representing the size of the spacer. Can be `small`, `large` or `flexible`.

View File

@@ -217,11 +217,9 @@ Sets the `image` associated with this tray icon when pressed on macOS.
Sets the hover text for this tray icon.
#### `tray.setTitle(title[, options])` _macOS_
#### `tray.setTitle(title)` _macOS_
* `title` String
* `options` Object (optional)
* `fontType` String (optional) - The font family variant to display, can be `monospaced` or `monospacedDigit`. `monospaced` is available in macOS 10.15+ and `monospacedDigit` is available in macOS 10.11+. When left blank, the title uses the default system font.
Sets the title displayed next to the tray icon in the status bar (Support ANSI colors).

View File

@@ -12,10 +12,10 @@ the [`BrowserWindow`](browser-window.md) object. An example of accessing the
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ width: 800, height: 1500 })
let win = new BrowserWindow({ width: 800, height: 1500 })
win.loadURL('http://github.com')
const contents = win.webContents
let contents = win.webContents
console.log(contents)
```
@@ -256,7 +256,7 @@ Returns:
Emitted after a server side redirect occurs during navigation. For example a 302
redirect.
This event cannot be prevented, if you want to prevent redirects you should
This event can not be prevented, if you want to prevent redirects you should
checkout out the `will-redirect` event above.
#### Event: 'did-navigate'
@@ -348,7 +348,7 @@ Returns:
Emitted when the renderer process crashes or is killed.
**Deprecated:** This event is superceded by the `render-process-gone` event
which contains more information about why the render process disappeared. It
which contains more information about why the render process dissapeared. It
isn't always because it crashed. The `killed` boolean can be replaced by
checking `reason === 'killed'` when you switch to that event.
@@ -367,7 +367,7 @@ Returns:
* `launch-failure` - Process never successfully launched
* `integrity-failure` - Windows code integrity checks failed
Emitted when the renderer process unexpectedly disappears. This is normally
Emitted when the renderer process unexpectedly dissapears. This is normally
because it was crashed or killed.
#### Event: 'unresponsive'
@@ -402,7 +402,6 @@ Returns:
* `key` String - Equivalent to [KeyboardEvent.key][keyboardevent].
* `code` String - Equivalent to [KeyboardEvent.code][keyboardevent].
* `isAutoRepeat` Boolean - Equivalent to [KeyboardEvent.repeat][keyboardevent].
* `isComposing` Boolean - Equivalent to [KeyboardEvent.isComposing][keyboardevent].
* `shift` Boolean - Equivalent to [KeyboardEvent.shiftKey][keyboardevent].
* `control` Boolean - Equivalent to [KeyboardEvent.controlKey][keyboardevent].
* `alt` Boolean - Equivalent to [KeyboardEvent.altKey][keyboardevent].
@@ -418,7 +417,7 @@ To only prevent the menu shortcuts, use
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600 })
let win = new BrowserWindow({ width: 800, height: 600 })
win.webContents.on('before-input-event', (event, input) => {
// For example, only enable application menu keyboard shortcuts when
@@ -665,7 +664,7 @@ app.whenReady().then(() => {
win = new BrowserWindow({ width: 800, height: 600 })
win.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
event.preventDefault()
const result = deviceList.find((device) => {
let result = deviceList.find((device) => {
return device.deviceName === 'test'
})
if (!result) {
@@ -691,7 +690,7 @@ buffer.
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ webPreferences: { offscreen: true } })
let win = new BrowserWindow({ webPreferences: { offscreen: true } })
win.webContents.on('paint', (event, dirty, image) => {
// updateBitmap(dirty, image.getBitmap())
})
@@ -720,7 +719,7 @@ This event can be used to configure `webPreferences` for the `webContents`
of a `<webview>` before it's loaded, and provides the ability to set settings
that can't be set via `<webview>` attributes.
**Note:** The specified `preload` script option will appear as `preloadURL`
**Note:** The specified `preload` script option will be appear as `preloadURL`
(not `preload`) in the `webPreferences` object emitted with this event.
#### Event: 'did-attach-webview'
@@ -738,9 +737,9 @@ Emitted when a `<webview>` has been attached to this web contents.
Returns:
* `event` Event
* `level` Integer - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
* `message` String - The actual console message
* `line` Integer - The line number of the source that triggered this console message
* `level` Integer
* `message` String
* `line` Integer
* `sourceId` String
Emitted when the associated window logs a console message.
@@ -907,11 +906,11 @@ Returns `String` - The URL of the current web page.
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com').then(() => {
const currentURL = win.webContents.getURL()
console.log(currentURL)
})
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')
let currentURL = win.webContents.getURL()
console.log(currentURL)
```
#### `contents.getTitle()`
@@ -1255,7 +1254,7 @@ is large then 0.
#### `contents.incrementCapturerCount([size, stayHidden])`
* `size` [Size](structures/size.md) (optional) - The preferred size for the capturer.
* `size` [Size](structures/size.md) (optional) - The perferred size for the capturer.
* `stayHidden` Boolean (optional) - Keep the page hidden instead of visible.
Increase the capturer count by one. The page is considered visible when its browser window is
@@ -1311,8 +1310,6 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
* `success` Boolean - Indicates success of the print call.
* `failureReason` String - Error description called back if the print fails.
When a custom `pageSize` is passed, Chromium attempts to validate platform specific minimum values for `width_microns` and `height_microns`. Width and height must both be minimum 353 microns but may be higher on some operating systems.
Prints window's web page. When `silent` is set to `true`, Electron will pick
the system's default printer if `deviceName` is empty and the default settings for printing.
@@ -1321,14 +1318,7 @@ Use `page-break-before: always;` CSS style to force to print to a new page.
Example usage:
```js
const options = {
silent: true,
deviceName: 'My-Printer',
pageRanges: {
from: 0,
to: 1
}
}
const options = { silent: true, deviceName: 'My-Printer' }
win.webContents.print(options, (success, errorType) => {
if (!success) console.log(errorType)
})
@@ -1343,12 +1333,13 @@ win.webContents.print(options, (success, errorType) => {
* `landscape` Boolean (optional) - `true` for landscape, `false` for portrait.
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
default margin, 1 for no margin, and 2 for minimum margin.
and `width` in microns.
* `scaleFactor` Number (optional) - The scale factor of the web page. Can range from 0 to 100.
* `pageRanges` Record<string, number> (optional) - The page range to print.
* `from` Number - zero-based index of the first page to print.
* `to` Number - zero-based index of the last page to print (inclusive).
* `from` Number - the first page to print.
* `to` Number - the last page to print (inclusive).
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width` in microns.
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
* `printSelectionOnly` Boolean (optional) - Whether to print selection only.
@@ -1379,22 +1370,19 @@ An example of `webContents.printToPDF`:
```javascript
const { BrowserWindow } = require('electron')
const fs = require('fs')
const path = require('path')
const os = require('os')
const win = new BrowserWindow({ width: 800, height: 600 })
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')
win.webContents.on('did-finish-load', () => {
// Use default printing options
win.webContents.printToPDF({}).then(data => {
const pdfPath = path.join(os.homedir(), 'Desktop', 'temp.pdf')
fs.writeFile(pdfPath, data, (error) => {
fs.writeFile('/tmp/print.pdf', data, (error) => {
if (error) throw error
console.log(`Wrote PDF successfully to ${pdfPath}`)
console.log('Write PDF successfully.')
})
}).catch(error => {
console.log(`Failed to write PDF to ${pdfPath}: `, error)
console.log(error)
})
})
```
@@ -1408,7 +1396,7 @@ creation:
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
let win = new BrowserWindow()
win.webContents.on('devtools-opened', () => {
win.webContents.addWorkSpace(__dirname)
})
@@ -1729,7 +1717,7 @@ Returns `Promise<void>` - resolves if the page is saved.
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
let win = new BrowserWindow()
win.loadURL('https://github.com')

View File

@@ -561,8 +561,8 @@ Stops any `findInPage` request for the `webview` with the provided `action`.
* `collate` Boolean (optional) - Whether the web page should be collated.
* `copies` Number (optional) - The number of copies of the web page to print.
* `pageRanges` Record<string, number> (optional) - The page range to print.
* `from` Number - zero-based index of the first page to print.
* `to` Number - zero-based index of the last page to print (inclusive).
* `from` Number - the start page.
* `to` Number - the end page.
* `duplexMode` String (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
* `dpi` Record<string, number> (optional)
* `horizontal` Number (optional) - The horizontal dpi.
@@ -755,9 +755,9 @@ Fired when page leaves fullscreen triggered by HTML API.
Returns:
* `level` Integer - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
* `message` String - The actual console message
* `line` Integer - The line number of the source that triggered this console message
* `level` Integer
* `message` String
* `line` Integer
* `sourceId` String
Fired when the guest window logs a console message.
@@ -816,7 +816,7 @@ const { shell } = require('electron')
const webview = document.querySelector('webview')
webview.addEventListener('new-window', async (e) => {
const protocol = (new URL(e.url)).protocol
const protocol = require('url').parse(e.url).protocol
if (protocol === 'http:' || protocol === 'https:') {
await shell.openExternal(e.url)
}

View File

@@ -94,6 +94,6 @@ mainWindow.webContents.on('new-window', (event, url, frameName, disposition, opt
```javascript
// renderer process (mainWindow)
const modal = window.open('', 'modal')
let modal = window.open('', 'modal')
modal.document.write('<h1>Hello</h1>')
```

View File

@@ -14,15 +14,6 @@ This document uses the following convention to categorize breaking changes:
## Planned Breaking API Changes (12.0)
### Default Changed: `contextIsolation` defaults to `true`
In Electron 12, `contextIsolation` will be enabled by default. To restore
the previous behavior, `contextIsolation: false` must be specified in WebPreferences.
We [recommend having contextIsolation enabled](https://github.com/electron/electron/blob/master/docs/tutorial/security.md#3-enable-context-isolation-for-remote-content) for the security of your application.
For more details see: https://github.com/electron/electron/issues/23506
### Removed: `crashReporter` methods in the renderer process
The following `crashReporter` methods are no longer available in the renderer
@@ -266,7 +257,7 @@ const getGuestForWebContents = (webContentsId, contents) => {
throw new Error(`Invalid webContentsId: ${webContentsId}`)
}
if (guest.hostWebContents !== contents) {
throw new Error('Access denied to webContents')
throw new Error(`Access denied to webContents`)
}
return guest
}
@@ -322,7 +313,7 @@ powerMonitor.querySystemIdleState(threshold, callback)
const idleState = powerMonitor.getSystemIdleState(threshold)
```
### API Changed: `powerMonitor.querySystemIdleTime` is now `powerMonitor.getSystemIdleTime`
### API Changed: `powerMonitor.querySystemIdleTime` is now `powerMonitor.getSystemIdleState`
```js
// Removed in Electron 7.0
@@ -610,11 +601,11 @@ const { memory } = metrics[0] // Deprecated property
```js
// Deprecated
const optionsA = { webPreferences: { blinkFeatures: '' } }
const windowA = new BrowserWindow(optionsA)
let optionsA = { webPreferences: { blinkFeatures: '' } }
let windowA = new BrowserWindow(optionsA)
// Replace with
const optionsB = { webPreferences: { enableBlinkFeatures: '' } }
const windowB = new BrowserWindow(optionsB)
let optionsB = { webPreferences: { enableBlinkFeatures: '' } }
let windowB = new BrowserWindow(optionsB)
// Deprecated
window.on('app-command', (e, cmd) => {
@@ -785,11 +776,11 @@ The following list includes the breaking API changes made in Electron 2.0.
```js
// Deprecated
const optionsA = { titleBarStyle: 'hidden-inset' }
const windowA = new BrowserWindow(optionsA)
let optionsA = { titleBarStyle: 'hidden-inset' }
let windowA = new BrowserWindow(optionsA)
// Replace with
const optionsB = { titleBarStyle: 'hiddenInset' }
const windowB = new BrowserWindow(optionsB)
let optionsB = { titleBarStyle: 'hiddenInset' }
let windowB = new BrowserWindow(optionsB)
```
### `menu`

View File

@@ -23,3 +23,4 @@ For guides on Electron app development, see
* [Debugging on macOS](debugging-instructions-macos.md)
* [Setting Up Symbol Server in Debugger](setting-up-symbol-server.md)
* [Patches](patches.md)
* [Upgrading Node](upgrading-node.md)

View File

@@ -10,10 +10,6 @@ Check the build prerequisites for your platform before proceeding
* [Linux](build-instructions-linux.md#prerequisites)
* [Windows](build-instructions-windows.md#prerequisites)
## Build Tools
[Electron's Build Tools](https://github.com/electron/build-tools) automate much of the setup for compiling Electron from source with different configurations and build targets. If you wish to set up the environment manually, the instructions are listed below.
## GN prerequisites
You'll need to install [`depot_tools`][depot-tools], the toolset

View File

@@ -233,7 +233,7 @@ Try not to be discouraged. If you feel that a review is unfair, say so or seek
the input of another project contributor. Often such comments are the result of
a reviewer having taken insufficient time to review and are not ill-intended.
Such difficulties can often be resolved with a bit of patience. That said,
reviewers should be expected to provide helpful feedback.
reviewers should be expected to provide helpful feeback.
### Step 11: Landing

View File

@@ -15,7 +15,7 @@ calls, and other compiler optimizations. The only workaround is to build an
unoptimized local build.
The official symbol server URL for Electron is
https://symbols.electronjs.org.
https://electron-symbols.githubapp.com.
You cannot visit this URL directly, you must add it to the symbol path of your
debugging tool. In the examples below, a local cache directory is used to avoid
repeatedly fetching the PDB from the server. Replace `c:\code\symbols` with an
@@ -30,7 +30,7 @@ directory on your computer, if you'd prefer a different location for downloaded
symbols):
```powershell
SRV*c:\code\symbols\*https://symbols.electronjs.org
SRV*c:\code\symbols\*https://electron-symbols.githubapp.com
```
Set this string as `_NT_SYMBOL_PATH` in the environment, using the Windbg menus,
@@ -38,7 +38,7 @@ or by typing the `.sympath` command. If you would like to get symbols from
Microsoft's symbol server as well, you should list that first:
```powershell
SRV*c:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*c:\code\symbols\*https://symbols.electronjs.org
SRV*c:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*c:\code\symbols\*https://electron-symbols.githubapp.com
```
## Using the symbol server in Visual Studio

View File

@@ -0,0 +1,121 @@
# Upgrading Node
## Discussion
Chromium and Node.js both depend on V8, and Electron contains
only a single copy of V8, so it's important to ensure that the
version of V8 chosen is compatible with the build's version of
Node.js and Chromium.
Upgrading Node is much easier than upgrading Chromium, so fewer
conflicts arise if one upgrades Chromium first, then chooses the
upstream Node release whose version of V8 is closest to the one
Chromium contains.
Electron has its own [Node fork](https://github.com/electron/node)
with modifications for the V8 build details mentioned above
and for exposing API needed by Electron. Once an upstream Node
release is chosen, it's placed in a branch in Electron's Node fork
and any Electron Node patches are applied there.
Another factor is that the Node project patches its version of V8.
As mentioned above, Electron builds everything with a single copy
of V8, so Node's V8 patches must be ported to that copy.
Once all of Electron's dependencies are building and using the same
copy of V8, the next step is to fix any Electron code issues caused
by the Node upgrade.
[FIXME] something about a Node debugger in Atom that we (e.g. deepak)
use and need to confirm doesn't break with the Node upgrade?
So in short, the primary steps are:
1. Update Electron's Node fork to the desired version
2. Backport Node's V8 patches to our copy of V8
3. Update the GN build files, porting changes from node's GYP files
4. Update Electron's DEPS to use new version of Node
## Updating Electron's Node [fork](https://github.com/electron/node)
1. Ensure that `master` on `electron/node` has updated release tags from `nodejs/node`
2. Create a branch in https://github.com/electron/node: `electron-node-vX.X.X` where the base that you're branching from is the tag for the desired update
- `vX.X.X` Must use a version of Node compatible with our current version of Chromium
3. Re-apply our commits from the previous version of Node we were using (`vY.Y.Y`) to `v.X.X.X`
- Check release tag and select the range of commits we need to re-apply
- Cherry-pick commit range:
1. Checkout both `vY.Y.Y` & `v.X.X.X`
2. `git cherry-pick FIRST_COMMIT_HASH..LAST_COMMIT_HASH`
- Resolve merge conflicts in each file encountered, then:
1. `git add <conflict-file>`
2. `git cherry-pick --continue`
3. Repeat until finished
## Updating [V8](https://github.com/electron/node/src/V8) Patches
We need to generate a patch file from each patch that Node
applies to V8.
```sh
$ cd third_party/electron_node
$ CURRENT_NODE_VERSION=vX.Y.Z
# Find the last commit with the message "deps: update V8 to <some version>"
# This commit corresponds to Node resetting V8 to its pristine upstream
# state at the stated version.
$ LAST_V8_UPDATE="$(git log --grep='^deps: update V8' --format='%H' -1 deps/v8)"
# This creates a patch file containing all changes in deps/v8 from
# $LAST_V8_UPDATE up to the current Node version, formatted in a way that
# it will apply cleanly to the V8 repository (i.e. with `deps/v8`
# stripped off the path and excluding the v8/gypfiles directory, which
# isn't present in V8.
$ git format-patch \
--relative=deps/v8 \
$LAST_V8_UPDATE..$CURRENT_NODE_VERSION \
deps/v8 \
':(exclude)deps/v8/gypfiles' \
--stdout \
> ../../electron/common/patches/v8/node_v8_patches.patch
```
This list of patches will probably include one that claims to
make the V8 API backwards-compatible with a previous version of
V8. Unfortunately, those patches almost always change the V8 API
in a way that is incompatible with Chromium.
It's usually easier to update Node to work without the
compatibility patch than to update Chromium to work with the
compatibility patch, so it's recommended to revert the
compatibility patch and fix any errors that arise when compiling
Node.
## Update Electron's `DEPS` file
Update the `DEPS` file in the root of
[electron/electron](https://github.com/electron/electron) to
point to the git hash of the updated Node.
## Notes
- Node maintains its own fork of V8
- They backport a small amount of things as needed
- Documentation in Node about how [they work with V8](https://nodejs.org/api/v8.html)
- We update code such that we only use one copy of V8 across all of Electron
- E.g Electron, Chromium, and Node.js
- We dont track upstream closely due to logistics:
- Upstream uses multiple repos and so merging into a single repo
would result in lost history. So we only update when were planning
a Node version bump in Electron.
- Chromium is large and time-consuming to update, so we typically
choose the Node version based on which of its releases has a version
of V8 thats closest to the version in Chromium that were using.
- We sometimes have to wait for the next periodic Node release
because it will sync more closely with the version of V8 in the new Chromium
- Electron keeps all its patches in the repo because its simpler than
maintaining different repos for patches for each upstream project.
- Crashpad, Node.js, Chromium, Skia etc. patches are all kept in the same place
- Building Node:
- We maintain our own GN build files for Node.js to make it easier to ensure
that eevrything is built with the same compiler flags.
This means that every time we upgrade Node.js we have to do a modest amount of
work to synchronize the GN files with the upstream GYP files.

View File

@@ -43,14 +43,26 @@ use HTML5 APIs which are already available in browsers. Good candidates are
[Storage API][storage], [`localStorage`][local-storage],
[`sessionStorage`][session-storage], and [IndexedDB][indexed-db].
Alternatively, you can use the IPC primitives that are provided by Electron. To
share data between the main and renderer processes, you can use the
[`ipcMain`](api/ipc-main.md) and [`ipcRenderer`](api/ipc-renderer.md) modules.
To communicate directly between web pages, you can send a
[`MessagePort`][message-port] from one to the other, possibly via the main process
using [`ipcRenderer.postMessage()`](api/ipc-renderer.md#ipcrendererpostmessagechannel-message-transfer).
Subsequent communication over message ports is direct and does not detour through
the main process.
Or you can use the IPC system, which is specific to Electron, to store objects
in the main process as a global variable, and then to access them from the
renderers through the `remote` property of `electron` module:
```javascript
// In the main process.
global.sharedObject = {
someProperty: 'default value'
}
```
```javascript
// In page 1.
require('electron').remote.getGlobal('sharedObject').someProperty = 'new value'
```
```javascript
// In page 2.
console.log(require('electron').remote.getGlobal('sharedObject').someProperty)
```
## My app's tray disappeared after a few minutes.
@@ -95,7 +107,7 @@ To solve this, you can turn off node integration in Electron:
```javascript
// In the main process.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
let win = new BrowserWindow({
webPreferences: {
nodeIntegration: false
}
@@ -143,7 +155,7 @@ To achieve this goal, set the background in the constructor for [BrowserWindow][
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
let win = new BrowserWindow({
backgroundColor: '#fff'
})
```
@@ -159,6 +171,5 @@ Notice that just setting the background in the CSS does not have the desired eff
[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
[message-port]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort
[browser-window]: api/browser-window.md
[subpixel rendering example]: images/subpixel-rendering-screenshot.gif

View File

@@ -1,95 +1,95 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('open-error-dialog', event => {
dialog.showErrorBox('An Error Message', 'Demonstrating an error message.')
})
ipcMain.on('open-information-dialog', event => {
const options = {
type: 'info',
title: 'Information',
message: "This is an information dialog. Isn't it nice?",
buttons: ['Yes', 'No']
}
dialog.showMessageBox(options, index => {
event.sender.send('information-dialog-selection', index)
})
})
ipcMain.on('open-file-dialog', event => {
dialog.showOpenDialog(
{
properties: ['openFile', 'openDirectory']
},
files => {
if (files) {
event.sender.send('selected-directory', files)
}
}
)
})
ipcMain.on('save-dialog', event => {
const options = {
title: 'Save an Image',
filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]
}
dialog.showSaveDialog(options, filename => {
event.sender.send('saved-file', filename)
})
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('open-error-dialog', event => {
dialog.showErrorBox('An Error Message', 'Demonstrating an error message.')
})
ipcMain.on('open-information-dialog', event => {
const options = {
type: 'info',
title: 'Information',
message: "This is an information dialog. Isn't it nice?",
buttons: ['Yes', 'No']
}
dialog.showMessageBox(options, index => {
event.sender.send('information-dialog-selection', index)
})
})
ipcMain.on('open-file-dialog', event => {
dialog.showOpenDialog(
{
properties: ['openFile', 'openDirectory']
},
files => {
if (files) {
event.sender.send('selected-directory', files)
}
}
)
})
ipcMain.on('save-dialog', event => {
const options = {
title: 'Save an Image',
filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]
}
dialog.showSaveDialog(options, filename => {
event.sender.send('saved-file', filename)
})
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -1,18 +1,18 @@
const { ipcRenderer, shell } = require('electron')
const links = document.querySelectorAll('a[href]')
const errorBtn = document.getElementById('error-dialog')
errorBtn.addEventListener('click', event => {
ipcRenderer.send('open-error-dialog')
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
const { ipcRenderer, shell } = require('electron')
const links = document.querySelectorAll('a[href]')
const errorBtn = document.getElementById('error-dialog')
errorBtn.addEventListener('click', event => {
ipcRenderer.send('open-error-dialog')
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})

View File

@@ -1,70 +1,70 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('open-information-dialog', event => {
const options = {
type: 'info',
title: 'Information',
message: "This is an information dialog. Isn't it nice?",
buttons: ['Yes', 'No']
}
dialog.showMessageBox(options, index => {
event.sender.send('information-dialog-selection', index)
})
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('open-information-dialog', event => {
const options = {
type: 'info',
title: 'Information',
message: "This is an information dialog. Isn't it nice?",
buttons: ['Yes', 'No']
}
dialog.showMessageBox(options, index => {
event.sender.send('information-dialog-selection', index)
})
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -1,25 +1,25 @@
const { ipcRenderer, shell } = require('electron')
const informationBtn = document.getElementById('information-dialog')
const links = document.querySelectorAll('a[href]')
informationBtn.addEventListener('click', event => {
ipcRenderer.send('open-information-dialog')
})
ipcRenderer.on('information-dialog-selection', (event, index) => {
let message = 'You selected '
if (index === 0) message += 'yes.'
else message += 'no.'
document.getElementById('info-selection').innerHTML = message
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
const { ipcRenderer, shell } = require('electron')
const informationBtn = document.getElementById('information-dialog')
const links = document.querySelectorAll('a[href]')
informationBtn.addEventListener('click', event => {
ipcRenderer.send('open-information-dialog')
})
ipcRenderer.on('information-dialog-selection', (event, index) => {
let message = 'You selected '
if (index === 0) message += 'yes.'
else message += 'no.'
document.getElementById('info-selection').innerHTML = message
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})

View File

@@ -1,70 +1,70 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('open-file-dialog', event => {
dialog.showOpenDialog(
{
properties: ['openFile', 'openDirectory']
},
files => {
if (files) {
event.sender.send('selected-directory', files)
}
}
)
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('open-file-dialog', event => {
dialog.showOpenDialog(
{
properties: ['openFile', 'openDirectory']
},
files => {
if (files) {
event.sender.send('selected-directory', files)
}
}
)
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -1,22 +1,22 @@
const { ipcRenderer, shell } = require('electron')
const selectDirBtn = document.getElementById('select-directory')
const links = document.querySelectorAll('a[href]')
selectDirBtn.addEventListener('click', event => {
ipcRenderer.send('open-file-dialog')
})
ipcRenderer.on('selected-directory', (event, path) => {
document.getElementById('selected-file').innerHTML = `You selected: ${path}`
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})
const { ipcRenderer, shell } = require('electron')
const selectDirBtn = document.getElementById('select-directory')
const links = document.querySelectorAll('a[href]')
selectDirBtn.addEventListener('click', event => {
ipcRenderer.send('open-file-dialog')
})
ipcRenderer.on('selected-directory', (event, path) => {
document.getElementById('selected-file').innerHTML = `You selected: ${path}`
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})

View File

@@ -1,66 +1,66 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('save-dialog', event => {
const options = {
title: 'Save an Image',
filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]
}
dialog.showSaveDialog(options, filename => {
event.sender.send('saved-file', filename)
})
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
ipcMain.on('save-dialog', event => {
const options = {
title: 'Save an Image',
filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]
}
dialog.showSaveDialog(options, filename => {
event.sender.send('saved-file', filename)
})
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -1,23 +1,23 @@
const { ipcRenderer, shell } = require('electron')
const saveBtn = document.getElementById('save-dialog')
const links = document.querySelectorAll('a[href]')
saveBtn.addEventListener('click', event => {
ipcRenderer.send('save-dialog')
})
ipcRenderer.on('saved-file', (event, path) => {
if (!path) path = 'No path'
document.getElementById('file-saved').innerHTML = `Path selected: ${path}`
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
const { ipcRenderer, shell } = require('electron')
const saveBtn = document.getElementById('save-dialog')
const links = document.querySelectorAll('a[href]')
saveBtn.addEventListener('click', event => {
ipcRenderer.send('save-dialog')
})
ipcRenderer.on('saved-file', (event, path) => {
if (!path) path = 'No path'
document.getElementById('file-saved').innerHTML = `Path selected: ${path}`
})
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})

View File

@@ -1,56 +1,56 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -1,13 +1,13 @@
const { shell } = require('electron')
const os = require('os')
const exLinksBtn = document.getElementById('open-ex-links')
const fileManagerBtn = document.getElementById('open-file-manager')
fileManagerBtn.addEventListener('click', (event) => {
shell.showItemInFolder(os.homedir())
})
exLinksBtn.addEventListener('click', (event) => {
shell.openExternal('https://electronjs.org')
const { shell } = require('electron')
const os = require('os')
const exLinksBtn = document.getElementById('open-ex-links')
const fileManagerBtn = document.getElementById('open-file-manager')
fileManagerBtn.addEventListener('click', (event) => {
shell.showItemInFolder(os.homedir())
})
exLinksBtn.addEventListener('click', (event) => {
shell.openExternal('https://electronjs.org')
})

View File

@@ -1,56 +1,56 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -1,29 +1,29 @@
const basicNotification = {
title: 'Basic Notification',
body: 'Short message part'
}
const notification = {
title: 'Notification with image',
body: 'Short message plus a custom image',
icon: 'https://via.placeholder.com/150'
}
const basicNotificationButton = document.getElementById('basic-noti')
const notificationButton = document.getElementById('advanced-noti')
notificationButton.addEventListener('click', () => {
const myNotification = new window.Notification(notification.title, notification)
myNotification.onclick = () => {
console.log('Notification clicked')
}
})
basicNotificationButton.addEventListener('click', () => {
const myNotification = new window.Notification(basicNotification.title, basicNotification)
myNotification.onclick = () => {
console.log('Notification clicked')
}
})
const basicNotification = {
title: 'Basic Notification',
body: 'Short message part'
}
const notification = {
title: 'Notification with image',
body: 'Short message plus a custom image',
icon: 'https://via.placeholder.com/150'
}
const basicNotificationButton = document.getElementById('basic-noti')
const notificationButton = document.getElementById('advanced-noti')
notificationButton.addEventListener('click', () => {
const myNotification = new window.Notification(notification.title, notification)
myNotification.onclick = () => {
console.log('Notification clicked')
}
})
basicNotificationButton.addEventListener('click', () => {
const myNotification = new window.Notification(basicNotification.title, basicNotification)
myNotification.onclick = () => {
console.log('Notification clicked')
}
})

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More