Compare commits
126 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f30034d1a9 | ||
|
|
00b6524793 | ||
|
|
f8f08814a2 | ||
|
|
0a758c418c | ||
|
|
daff2057a4 | ||
|
|
67f2f9e024 | ||
|
|
3ee1a45d76 | ||
|
|
652d87282a | ||
|
|
923788b4e4 | ||
|
|
541504c8a4 | ||
|
|
490584834e | ||
|
|
a269ebd1d8 | ||
|
|
0f073186ff | ||
|
|
73e216f182 | ||
|
|
0a80eb4a9c | ||
|
|
50e386ead4 | ||
|
|
5f0810a177 | ||
|
|
65f3729bfb | ||
|
|
b5bdd26a45 | ||
|
|
9ac2ee317d | ||
|
|
a600027384 | ||
|
|
7f82836d67 | ||
|
|
769088f8dc | ||
|
|
c85bc3c932 | ||
|
|
3cd795a927 | ||
|
|
6179b03fa1 | ||
|
|
72c48aa400 | ||
|
|
befe53e5ad | ||
|
|
41aaed307d | ||
|
|
0d17fac455 | ||
|
|
5c3d6aaa81 | ||
|
|
da6996dc63 | ||
|
|
4cfa648a2e | ||
|
|
86294aa1d0 | ||
|
|
50d9fd215e | ||
|
|
06b3615e30 | ||
|
|
8680415128 | ||
|
|
35bf159cd3 | ||
|
|
f8c7408279 | ||
|
|
9b1e7a8963 | ||
|
|
765e1025f4 | ||
|
|
a5d2a56105 | ||
|
|
d8f43ed7bd | ||
|
|
f1b30c26f9 | ||
|
|
c80f701085 | ||
|
|
fa6dde3e1c | ||
|
|
bb6a072380 | ||
|
|
743e442796 | ||
|
|
4abb7e9709 | ||
|
|
8b996a478a | ||
|
|
d36dc1c7de | ||
|
|
e5c56c08a4 | ||
|
|
1763f4cfc8 | ||
|
|
700887d623 | ||
|
|
f893707c5d | ||
|
|
dcf825bed6 | ||
|
|
cee4e3707f | ||
|
|
e9fa834757 | ||
|
|
a327684118 | ||
|
|
ef5424cee0 | ||
|
|
388acd7e2a | ||
|
|
46d74390fc | ||
|
|
d305082ab7 | ||
|
|
0370583c73 | ||
|
|
91274e5a7e | ||
|
|
fc3172dd2a | ||
|
|
7e0b787a76 | ||
|
|
4556adde82 | ||
|
|
7283c257ae | ||
|
|
bf5a0cdd6a | ||
|
|
1c8e9b3651 | ||
|
|
90726a46e1 | ||
|
|
9cd76a8e52 | ||
|
|
a9b17793de | ||
|
|
134042cc43 | ||
|
|
26d729a4a3 | ||
|
|
68c3c3f7ad | ||
|
|
92cd3d1fa5 | ||
|
|
47f8a13384 | ||
|
|
19c3e1c8b7 | ||
|
|
7e771a3db5 | ||
|
|
c5ec2099bb | ||
|
|
262cc48ad0 | ||
|
|
fb5741efd6 | ||
|
|
47669c55fd | ||
|
|
7b76a70e07 | ||
|
|
b4466f8f3e | ||
|
|
2e9ccd4372 | ||
|
|
1528b0d307 | ||
|
|
da86676a43 | ||
|
|
0579822008 | ||
|
|
ff64cd722f | ||
|
|
fea2aabdd4 | ||
|
|
3bbbf4b27f | ||
|
|
6dc7384f3a | ||
|
|
68c541380e | ||
|
|
fe8c831a0c | ||
|
|
cc9ba35c51 | ||
|
|
56ccfad7a5 | ||
|
|
47bda9c0e5 | ||
|
|
4f27c367b1 | ||
|
|
339ae4c014 | ||
|
|
c1f4b6a4cb | ||
|
|
0a908224c2 | ||
|
|
34c4889bbb | ||
|
|
8c066c2a35 | ||
|
|
7c9b609389 | ||
|
|
7ab85558f5 | ||
|
|
ca06034fdd | ||
|
|
d07fe4480f | ||
|
|
c2195915d8 | ||
|
|
57408e4c2a | ||
|
|
0012e01c86 | ||
|
|
2b97ff3fba | ||
|
|
87590da2fb | ||
|
|
493751b321 | ||
|
|
36008e0dea | ||
|
|
2871698148 | ||
|
|
9d8dde5c76 | ||
|
|
f72efecf95 | ||
|
|
5b45cb3f77 | ||
|
|
ad2b136425 | ||
|
|
94f4c18d7c | ||
|
|
f7f41fee99 | ||
|
|
907e9c8c0e | ||
|
|
4d2968bfc1 |
1
.circleci/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
config-staging
|
||||
@@ -6,7 +6,6 @@ setup: true
|
||||
# Orbs
|
||||
orbs:
|
||||
path-filtering: circleci/path-filtering@0.1.0
|
||||
continuation: circleci/continuation@0.2.0
|
||||
|
||||
# All input parameters to pass to build config
|
||||
parameters:
|
||||
@@ -14,7 +13,7 @@ parameters:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
upload-to-storage:
|
||||
upload-to-s3:
|
||||
type: string
|
||||
default: '1'
|
||||
|
||||
@@ -44,33 +43,103 @@ parameters:
|
||||
default: all
|
||||
enum: ["all", "osx-x64", "osx-arm64", "mas-x64", "mas-arm64"]
|
||||
|
||||
jobs:
|
||||
generate-config:
|
||||
# Envs
|
||||
env-global: &env-global
|
||||
ELECTRON_OUT_DIR: Default
|
||||
|
||||
env-linux-medium: &env-linux-medium
|
||||
<<: *env-global
|
||||
NUMBER_OF_NINJA_PROCESSES: 3
|
||||
|
||||
# Executors
|
||||
executors:
|
||||
linux-docker:
|
||||
parameters:
|
||||
size:
|
||||
description: "Docker executor size"
|
||||
default: 2xlarge+
|
||||
type: enum
|
||||
enum: ["medium", "xlarge", "2xlarge+"]
|
||||
docker:
|
||||
- image: cimg/node:16.14
|
||||
steps:
|
||||
- checkout
|
||||
- path-filtering/set-parameters:
|
||||
- image: ghcr.io/electron/build:27db4a3e3512bfd2e47f58cea69922da0835f1d9
|
||||
resource_class: << parameters.size >>
|
||||
|
||||
# List of always run steps
|
||||
step-checkout-electron: &step-checkout-electron
|
||||
checkout:
|
||||
path: src/electron
|
||||
|
||||
steps-lint: &steps-lint
|
||||
steps:
|
||||
- *step-checkout-electron
|
||||
- run:
|
||||
name: Setup third_party Depot Tools
|
||||
command: |
|
||||
# "depot_tools" has to be checkout into "//third_party/depot_tools" so pylint.py can a "pylintrc" file.
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git src/third_party/depot_tools
|
||||
echo 'export PATH="$PATH:'"$PWD"'/src/third_party/depot_tools"' >> $BASH_ENV
|
||||
- run:
|
||||
name: Download GN Binary
|
||||
command: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
gn_version="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)"
|
||||
|
||||
cipd ensure -ensure-file - -root . \<<-CIPD
|
||||
\$ServiceURL https://chrome-infra-packages.appspot.com/
|
||||
@Subdir src/buildtools/linux64
|
||||
gn/gn/linux-amd64 $gn_version
|
||||
CIPD
|
||||
|
||||
echo 'export CHROMIUM_BUILDTOOLS_PATH="'"$PWD"'/src/buildtools"' >> $BASH_ENV
|
||||
- run:
|
||||
name: Download clang-format Binary
|
||||
command: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
|
||||
sha1_path='buildtools/linux64/clang-format.sha1'
|
||||
curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/${sha1_path}?format=TEXT" | base64 -d > "src/${sha1_path}"
|
||||
|
||||
download_from_google_storage.py --no_resume --no_auth --bucket chromium-clang-format -s "src/${sha1_path}"
|
||||
- run:
|
||||
name: Run Lint
|
||||
command: |
|
||||
# gn.py tries to find a gclient root folder starting from the current dir.
|
||||
# When it fails and returns "None" path, the whole script fails. Let's "fix" it.
|
||||
touch .gclient
|
||||
# Another option would be to checkout "buildtools" inside the Electron checkout,
|
||||
# but then we would lint its contents (at least gn format), and it doesn't pass it.
|
||||
|
||||
cd src/electron
|
||||
node script/yarn install --frozen-lockfile
|
||||
node script/yarn lint
|
||||
- run:
|
||||
name: Run Script Typechecker
|
||||
command: |
|
||||
cd src/electron
|
||||
node script/yarn tsc -p tsconfig.script.json
|
||||
|
||||
# List of always run jobs.
|
||||
jobs:
|
||||
lint:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: medium
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *steps-lint
|
||||
|
||||
# Initial setup workflow
|
||||
workflows:
|
||||
lint:
|
||||
jobs:
|
||||
# Job inherited from path-filtering orb
|
||||
- path-filtering/filter:
|
||||
base-revision: main
|
||||
# Params for mapping; `path-to-test parameter-to-set value-for-parameter` for each row
|
||||
mapping: |
|
||||
^((?!docs/).)*$ run-build-mac true
|
||||
^((?!docs/).)*$ run-build-linux true
|
||||
docs/.* run-docs-only true
|
||||
^((?!docs/).)*$ run-docs-only false
|
||||
- run:
|
||||
command: |
|
||||
cd .circleci/config
|
||||
yarn
|
||||
export CIRCLECI_BINARY="$HOME/circleci"
|
||||
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | DESTDIR=$CIRCLECI_BINARY bash
|
||||
node build.js
|
||||
name: Pack config.yml
|
||||
- continuation/continue:
|
||||
configuration_path: .circleci/config-staging/built.yml
|
||||
parameters: /tmp/pipeline-parameters.json
|
||||
|
||||
# Initial setup workflow
|
||||
workflows:
|
||||
setup:
|
||||
jobs:
|
||||
- generate-config
|
||||
config-path: .circleci/build_config.yml
|
||||
- lint
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
const cp = require('child_process');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
const STAGING_DIR = path.resolve(__dirname, '..', 'config-staging');
|
||||
|
||||
function copyAndExpand(dir = './') {
|
||||
const absDir = path.resolve(__dirname, dir);
|
||||
const targetDir = path.resolve(STAGING_DIR, dir);
|
||||
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
fs.mkdirSync(targetDir);
|
||||
}
|
||||
|
||||
for (const file of fs.readdirSync(absDir)) {
|
||||
if (!file.endsWith('.yml')) {
|
||||
if (fs.statSync(path.resolve(absDir, file)).isDirectory()) {
|
||||
copyAndExpand(path.join(dir, file));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
fs.writeFileSync(path.resolve(targetDir, file), yaml.dump(yaml.load(fs.readFileSync(path.resolve(absDir, file), 'utf8')), {
|
||||
noRefs: true,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (fs.pathExists(STAGING_DIR)) fs.removeSync(STAGING_DIR);
|
||||
copyAndExpand();
|
||||
|
||||
const output = cp.spawnSync(process.env.CIRCLECI_BINARY || 'circleci', ['config', 'pack', STAGING_DIR]);
|
||||
fs.writeFileSync(path.resolve(STAGING_DIR, 'built.yml'), output.stdout.toString());
|
||||
@@ -1,51 +0,0 @@
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: medium
|
||||
steps:
|
||||
- checkout:
|
||||
path: src/electron
|
||||
- run:
|
||||
name: Setup third_party Depot Tools
|
||||
command: |
|
||||
# "depot_tools" has to be checkout into "//third_party/depot_tools" so pylint.py can a "pylintrc" file.
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git src/third_party/depot_tools
|
||||
echo 'export PATH="$PATH:'"$PWD"'/src/third_party/depot_tools"' >> $BASH_ENV
|
||||
- run:
|
||||
name: Download GN Binary
|
||||
command: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
gn_version="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)"
|
||||
|
||||
cipd ensure -ensure-file - -root . \<<-CIPD
|
||||
\$ServiceURL https://chrome-infra-packages.appspot.com/
|
||||
@Subdir src/buildtools/linux64
|
||||
gn/gn/linux-amd64 $gn_version
|
||||
CIPD
|
||||
|
||||
echo 'export CHROMIUM_BUILDTOOLS_PATH="'"$PWD"'/src/buildtools"' >> $BASH_ENV
|
||||
- run:
|
||||
name: Download clang-format Binary
|
||||
command: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
|
||||
sha1_path='buildtools/linux64/clang-format.sha1'
|
||||
curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/${sha1_path}?format=TEXT" | base64 -d > "src/${sha1_path}"
|
||||
|
||||
download_from_google_storage.py --no_resume --no_auth --bucket chromium-clang-format -s "src/${sha1_path}"
|
||||
- run:
|
||||
name: Run Lint
|
||||
command: |
|
||||
# gn.py tries to find a gclient root folder starting from the current dir.
|
||||
# When it fails and returns "None" path, the whole script fails. Let's "fix" it.
|
||||
touch .gclient
|
||||
# Another option would be to checkout "buildtools" inside the Electron checkout,
|
||||
# but then we would lint its contents (at least gn format), and it doesn't pass it.
|
||||
|
||||
cd src/electron
|
||||
node script/yarn install --frozen-lockfile
|
||||
node script/yarn lint
|
||||
- run:
|
||||
name: Run Script Typechecker
|
||||
command: |
|
||||
cd src/electron
|
||||
node script/yarn tsc -p tsconfig.script.json
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "@electron/circleci-config",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fs-extra": "^10.1.0",
|
||||
"js-yaml": "^4.1.0"
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
argparse@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||
|
||||
fs-extra@^10.1.0:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
|
||||
integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^2.0.0"
|
||||
|
||||
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
|
||||
version "4.2.10"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
|
||||
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
jsonfile@^6.0.1:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
|
||||
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
|
||||
dependencies:
|
||||
universalify "^2.0.0"
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
universalify@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
|
||||
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": "standard",
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": ["@typescript-eslint"],
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Atom --> Electron rename
|
||||
d9321f4df751fa32813fab1b6387bbd61bd681d0
|
||||
34c4c8d5088fa183f56baea28809de6f2a427e02
|
||||
# Enable JS Semicolons
|
||||
5d657dece4102e5e5304d42e8004b6ad64c0fcda
|
||||
9
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -17,11 +17,8 @@ body:
|
||||
- type: input
|
||||
attributes:
|
||||
label: Electron Version
|
||||
description: |
|
||||
What version of Electron are you using?
|
||||
|
||||
Note: Please only report issues for [currently supported versions of Electron](https://www.electronjs.org/docs/latest/tutorial/support#currently-supported-versions).
|
||||
placeholder: 17.0.0
|
||||
description: What version of Electron are you using?
|
||||
placeholder: 12.0.0
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
@@ -56,7 +53,7 @@ body:
|
||||
attributes:
|
||||
label: Last Known Working Electron version
|
||||
description: What is the last version of Electron this worked in, if applicable?
|
||||
placeholder: 16.0.0
|
||||
placeholder: 11.0.0
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
|
||||
2
.github/semantic.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Always validate the PR title, and ignore the commits
|
||||
titleOnly: true
|
||||
178
.github/workflows/electron_woa_testing.yml
vendored
@@ -1,178 +0,0 @@
|
||||
name: Electron WOA Testing
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: '**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
appveyor_job_id:
|
||||
description: 'Job Id of Appveyor WOA job to test'
|
||||
type: text
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
electron-woa-init:
|
||||
if: ${{ github.event_name == 'push' && github.repository == 'electron/electron' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dummy step for push event
|
||||
run: |
|
||||
echo "This job is a needed initialization step for Electron WOA testing. Another test result will appear once the electron-woa-testing build is done."
|
||||
|
||||
electron-woa-testing:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'electron/electron' }}
|
||||
runs-on: [self-hosted, woa]
|
||||
permissions:
|
||||
checks: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: LouisBrunner/checks-action@v1.1.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: electron-woa-testing
|
||||
status: in_progress
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
output: |
|
||||
{"summary":"Test In Progress","text_description":"See job details here: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}
|
||||
- name: Clean Workspace
|
||||
run: |
|
||||
Remove-Item * -Recurse -Force
|
||||
shell: powershell
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: src\electron
|
||||
fetch-depth: 0
|
||||
- name: Yarn install
|
||||
run: |
|
||||
cd src\electron
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
- name: Download and extract dist.zip for test
|
||||
run: |
|
||||
$localArtifactPath = "$pwd\dist.zip"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/dist.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -osrc\out\Default -y $localArtifactPath
|
||||
shell: powershell
|
||||
- name: Download and extract native test executables for test
|
||||
run: |
|
||||
$localArtifactPath = "src\out\Default\shell_browser_ui_unittests.exe"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/shell_browser_ui_unittests.exe"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
shell: powershell
|
||||
- name: Download and extract ffmpeg.zip for test
|
||||
run: |
|
||||
$localArtifactPath = "$pwd\ffmpeg.zip"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/ffmpeg.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -osrc\out\ffmpeg $localArtifactPath
|
||||
shell: powershell
|
||||
- name: Download node headers for test
|
||||
run: |
|
||||
$localArtifactPath = "src\node_headers.zip"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/node_headers.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
cd src
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y node_headers.zip
|
||||
shell: powershell
|
||||
- name: Download electron.lib for test
|
||||
run: |
|
||||
$localArtifactPath = "src\out\Default\electron.lib"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/electron.lib"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
shell: powershell
|
||||
# Uncomment the following block if pdb files are needed to debug issues
|
||||
# - name: Download pdb files for detailed stacktraces
|
||||
# if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
# run: |
|
||||
# try {
|
||||
# $localArtifactPath = "src\pdb.zip"
|
||||
# $serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/pdb.zip"
|
||||
# Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
# cd src
|
||||
# & "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y pdb.zip
|
||||
# } catch {
|
||||
# Write-Host "There was an exception encountered while downloading pdb files:" $_.Exception.Message
|
||||
# } finally {
|
||||
# $global:LASTEXITCODE = 0
|
||||
# }
|
||||
# shell: powershell
|
||||
- name: Setup node headers
|
||||
run: |
|
||||
New-Item src\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path src\out\Default\electron.lib -destination src\out\Default\gen\node_headers\Release\node.lib
|
||||
shell: powershell
|
||||
- name: Run Electron Main process tests
|
||||
run: |
|
||||
cd src
|
||||
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
node script/yarn test --runners=main --enable-logging --disable-features=CalculateNativeWinOcclusion
|
||||
env:
|
||||
ELECTRON_ENABLE_STACK_DUMPING: true
|
||||
ELECTRON_OUT_DIR: Default
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
ELECTRON_SKIP_NATIVE_MODULE_TESTS: true
|
||||
- name: Run Electron Remote based tests
|
||||
if: ${{ success() || failure() }}
|
||||
run: |
|
||||
cd src
|
||||
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
node script/yarn test --runners=remote --enable-logging --disable-features=CalculateNativeWinOcclusion
|
||||
env:
|
||||
ELECTRON_OUT_DIR: Default
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
ELECTRON_SKIP_NATIVE_MODULE_TESTS: true
|
||||
- name: Verify ffmpeg
|
||||
run: |
|
||||
cd src
|
||||
echo "Verifying non proprietary ffmpeg"
|
||||
python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
|
||||
shell: cmd
|
||||
- name: Kill processes left running from last test run
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
Get-Process | Where Name -Like "electron*" | Stop-Process
|
||||
Get-Process | Where Name -Like "msedge*" | Stop-Process
|
||||
shell: powershell
|
||||
- name: Delete user app data directories
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
Remove-Item -path $env:APPDATA/Electron* -Recurse -Force -ErrorAction Ignore
|
||||
shell: powershell
|
||||
- uses: LouisBrunner/checks-action@v1.1.1
|
||||
if: ${{ success() }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: electron-woa-testing
|
||||
conclusion: "${{ job.status }}"
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
output: |
|
||||
{"summary":"${{ job.status }}","text_description":"See job details here: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}
|
||||
- uses: LouisBrunner/checks-action@v1.1.1
|
||||
if: ${{ success() }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: electron-woa-testing
|
||||
conclusion: "${{ job.status }}"
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
output: |
|
||||
{"summary":"Job Succeeded","text_description":"See job details here: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}
|
||||
- uses: LouisBrunner/checks-action@v1.1.1
|
||||
if: ${{ ! success() }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: electron-woa-testing
|
||||
conclusion: "${{ job.status }}"
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
output: |
|
||||
{"summary":"Job Failed","text_description":"See job details here: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}
|
||||
26
.github/workflows/semantic.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: "Check Semantic Commit"
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
main:
|
||||
permissions:
|
||||
pull-requests: read # for amannn/action-semantic-pull-request to analyze PRs
|
||||
statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR
|
||||
name: Validate PR Title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: semantic-pull-request
|
||||
uses: amannn/action-semantic-pull-request@v4
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
validateSingleCommit: false
|
||||
@@ -23,5 +23,7 @@
|
||||
"br_spaces": 0
|
||||
},
|
||||
"single-h1": false,
|
||||
"no-inline-html": false
|
||||
"no-inline-html": {
|
||||
"allowed_elements": ["br"]
|
||||
}
|
||||
}
|
||||
|
||||
227
BUILD.gn
@@ -37,13 +37,12 @@ if (is_mac) {
|
||||
import("build/rules.gni")
|
||||
|
||||
assert(
|
||||
mac_deployment_target == "10.13",
|
||||
mac_deployment_target == "10.11.0",
|
||||
"Chromium has updated the mac_deployment_target, please update this assert, update the supported versions documentation (docs/tutorial/support.md) and flag this as a breaking change")
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
import("//build/config/linux/pkg_config.gni")
|
||||
import("//tools/generate_stubs/rules.gni")
|
||||
|
||||
pkg_config("gio_unix") {
|
||||
packages = [ "gio-unix-2.0" ]
|
||||
@@ -55,48 +54,6 @@ if (is_linux) {
|
||||
"gdk-pixbuf-2.0",
|
||||
]
|
||||
}
|
||||
|
||||
generate_library_loader("libnotify_loader") {
|
||||
name = "LibNotifyLoader"
|
||||
output_h = "libnotify_loader.h"
|
||||
output_cc = "libnotify_loader.cc"
|
||||
header = "<libnotify/notify.h>"
|
||||
config = ":libnotify_config"
|
||||
|
||||
functions = [
|
||||
"notify_is_initted",
|
||||
"notify_init",
|
||||
"notify_get_server_caps",
|
||||
"notify_get_server_info",
|
||||
"notify_notification_new",
|
||||
"notify_notification_add_action",
|
||||
"notify_notification_set_image_from_pixbuf",
|
||||
"notify_notification_set_timeout",
|
||||
"notify_notification_set_urgency",
|
||||
"notify_notification_set_hint_string",
|
||||
"notify_notification_show",
|
||||
"notify_notification_close",
|
||||
]
|
||||
}
|
||||
|
||||
# Generates electron_gtk_stubs.h header which contains
|
||||
# stubs for extracting function ptrs from the gtk library.
|
||||
# Function signatures for which stubs are required should be
|
||||
# declared in electron_gtk.sigs, currently this file contains
|
||||
# signatures for the functions used with native file chooser
|
||||
# implementation. In future, this file can be extended to contain
|
||||
# gtk4 stubs to switch gtk version in runtime.
|
||||
generate_stubs("electron_gtk_stubs") {
|
||||
sigs = [
|
||||
"shell/browser/ui/electron_gdk_pixbuf.sigs",
|
||||
"shell/browser/ui/electron_gtk.sigs",
|
||||
]
|
||||
extra_header = "shell/browser/ui/electron_gtk.fragment"
|
||||
output_name = "electron_gtk_stubs"
|
||||
public_deps = [ "//ui/gtk:gtk_config" ]
|
||||
logging_function = "LogNoop()"
|
||||
logging_include = "ui/gtk/log_noop.h"
|
||||
}
|
||||
}
|
||||
|
||||
declare_args() {
|
||||
@@ -107,14 +64,6 @@ branding = read_file("shell/app/BRANDING.json", "json")
|
||||
electron_project_name = branding.project_name
|
||||
electron_product_name = branding.product_name
|
||||
electron_mac_bundle_id = branding.mac_bundle_id
|
||||
electron_version = exec_script("script/print-version.py",
|
||||
[],
|
||||
"trim string",
|
||||
[
|
||||
".git/packed-refs",
|
||||
".git/HEAD",
|
||||
"script/lib/get-version.js",
|
||||
])
|
||||
|
||||
if (is_mas_build) {
|
||||
assert(is_mac,
|
||||
@@ -241,7 +190,6 @@ action("electron_js2c") {
|
||||
action("generate_config_gypi") {
|
||||
outputs = [ "$root_gen_dir/config.gypi" ]
|
||||
script = "script/generate-config-gypi.py"
|
||||
inputs = [ "//third_party/electron_node/configure.py" ]
|
||||
args = rebase_path(outputs) + [ target_cpu ]
|
||||
}
|
||||
|
||||
@@ -305,14 +253,42 @@ copy("copy_shell_devtools_discovery_page") {
|
||||
outputs = [ "$target_gen_dir/shell_devtools_discovery_page.html" ]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
generate_library_loader("libnotify_loader") {
|
||||
name = "LibNotifyLoader"
|
||||
output_h = "libnotify_loader.h"
|
||||
output_cc = "libnotify_loader.cc"
|
||||
header = "<libnotify/notify.h>"
|
||||
config = ":libnotify_config"
|
||||
|
||||
functions = [
|
||||
"notify_is_initted",
|
||||
"notify_init",
|
||||
"notify_get_server_caps",
|
||||
"notify_get_server_info",
|
||||
"notify_notification_new",
|
||||
"notify_notification_add_action",
|
||||
"notify_notification_set_image_from_pixbuf",
|
||||
"notify_notification_set_timeout",
|
||||
"notify_notification_set_urgency",
|
||||
"notify_notification_set_hint_string",
|
||||
"notify_notification_show",
|
||||
"notify_notification_close",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
npm_action("electron_version_args") {
|
||||
script = "generate-version-json"
|
||||
|
||||
outputs = [ "$target_gen_dir/electron_version.args" ]
|
||||
|
||||
args = rebase_path(outputs) + [ "$electron_version" ]
|
||||
args = rebase_path(outputs)
|
||||
|
||||
inputs = [ "script/generate-version-json.js" ]
|
||||
inputs = [
|
||||
"ELECTRON_VERSION",
|
||||
"script/generate-version-json.js",
|
||||
]
|
||||
}
|
||||
|
||||
templated_file("electron_version_header") {
|
||||
@@ -324,39 +300,6 @@ templated_file("electron_version_header") {
|
||||
args_files = get_target_outputs(":electron_version_args")
|
||||
}
|
||||
|
||||
templated_file("electron_win_rc") {
|
||||
deps = [ ":electron_version_args" ]
|
||||
|
||||
template = "build/templates/electron_rc.tmpl"
|
||||
output = "$target_gen_dir/win-resources/electron.rc"
|
||||
|
||||
args_files = get_target_outputs(":electron_version_args")
|
||||
}
|
||||
|
||||
copy("electron_win_resource_files") {
|
||||
sources = [
|
||||
"shell/browser/resources/win/electron.ico",
|
||||
"shell/browser/resources/win/resource.h",
|
||||
]
|
||||
outputs = [ "$target_gen_dir/win-resources/{{source_file_part}}" ]
|
||||
}
|
||||
|
||||
templated_file("electron_version_file") {
|
||||
deps = [ ":electron_version_args" ]
|
||||
|
||||
template = "build/templates/version_string.tmpl"
|
||||
output = "$root_build_dir/version"
|
||||
|
||||
args_files = get_target_outputs(":electron_version_args")
|
||||
}
|
||||
|
||||
group("electron_win32_resources") {
|
||||
public_deps = [
|
||||
":electron_win_rc",
|
||||
":electron_win_resource_files",
|
||||
]
|
||||
}
|
||||
|
||||
action("electron_fuses") {
|
||||
script = "build/fuses/build.py"
|
||||
|
||||
@@ -408,12 +351,10 @@ source_set("electron_lib") {
|
||||
"shell/common/api:mojo",
|
||||
"//base:base_static",
|
||||
"//base/allocator:buildflags",
|
||||
"//chrome:strings",
|
||||
"//chrome/app:command_ids",
|
||||
"//chrome/app/resources:platform_locale_settings",
|
||||
"//components/autofill/core/common:features",
|
||||
"//components/certificate_transparency",
|
||||
"//components/embedder_support:browser_util",
|
||||
"//components/language/core/browser",
|
||||
"//components/net_log",
|
||||
"//components/network_hints/browser",
|
||||
@@ -441,6 +382,9 @@ source_set("electron_lib") {
|
||||
"//media/mojo/mojom",
|
||||
"//net:extras",
|
||||
"//net:net_resources",
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/shared_impl",
|
||||
"//printing/buildflags",
|
||||
"//services/device/public/cpp/geolocation",
|
||||
"//services/device/public/cpp/hid",
|
||||
@@ -558,8 +502,6 @@ source_set("electron_lib") {
|
||||
"StoreKit.framework",
|
||||
]
|
||||
|
||||
weak_frameworks = [ "QuickLookThumbnailing.framework" ]
|
||||
|
||||
sources += [
|
||||
"shell/browser/ui/views/autofill_popup_view.cc",
|
||||
"shell/browser/ui/views/autofill_popup_view.h",
|
||||
@@ -593,7 +535,6 @@ source_set("electron_lib") {
|
||||
if (is_linux) {
|
||||
libs = [ "xshmfence" ]
|
||||
deps += [
|
||||
":electron_gtk_stubs",
|
||||
":libnotify_loader",
|
||||
"//build/config/linux/gtk",
|
||||
"//dbus",
|
||||
@@ -601,8 +542,8 @@ source_set("electron_lib") {
|
||||
"//ui/base/ime/linux",
|
||||
"//ui/events/devices/x11",
|
||||
"//ui/events/platform/x11",
|
||||
"//ui/gtk",
|
||||
"//ui/views/controls/webview",
|
||||
"//ui/views/linux_ui:linux_ui_factory",
|
||||
"//ui/wm",
|
||||
]
|
||||
if (ozone_platform_x11) {
|
||||
@@ -651,15 +592,8 @@ source_set("electron_lib") {
|
||||
}
|
||||
|
||||
if (enable_plugins) {
|
||||
deps += [
|
||||
"chromium_src:plugins",
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/shared_impl",
|
||||
]
|
||||
deps += [ "chromium_src:plugins" ]
|
||||
sources += [
|
||||
"shell/renderer/electron_renderer_pepper_host_factory.cc",
|
||||
"shell/renderer/electron_renderer_pepper_host_factory.h",
|
||||
"shell/renderer/pepper_helper.cc",
|
||||
"shell/renderer/pepper_helper.h",
|
||||
]
|
||||
@@ -763,7 +697,7 @@ source_set("electron_lib") {
|
||||
"//components/pdf/browser:interceptors",
|
||||
"//components/pdf/common",
|
||||
"//components/pdf/renderer",
|
||||
"//pdf",
|
||||
"//pdf:pdf_ppapi",
|
||||
]
|
||||
sources += [
|
||||
"shell/browser/electron_pdf_web_contents_helper_client.cc",
|
||||
@@ -773,6 +707,14 @@ source_set("electron_lib") {
|
||||
|
||||
sources += get_target_outputs(":electron_fuses")
|
||||
|
||||
if (is_win && enable_win_dark_mode_window_ui) {
|
||||
sources += [
|
||||
"shell/browser/win/dark_mode.cc",
|
||||
"shell/browser/win/dark_mode.h",
|
||||
]
|
||||
libs += [ "uxtheme.lib" ]
|
||||
}
|
||||
|
||||
if (allow_runtime_configurable_key_storage) {
|
||||
defines += [ "ALLOW_RUNTIME_CONFIGURABLE_KEY_STORAGE" ]
|
||||
}
|
||||
@@ -792,6 +734,7 @@ if (is_mac) {
|
||||
electron_helper_name = "$electron_product_name Helper"
|
||||
electron_login_helper_name = "$electron_product_name Login Helper"
|
||||
electron_framework_version = "A"
|
||||
electron_version = read_file("ELECTRON_VERSION", "trim string")
|
||||
|
||||
mac_xib_bundle_data("electron_xibs") {
|
||||
sources = [ "shell/common/resources/mac/MainMenu.xib" ]
|
||||
@@ -856,11 +799,16 @@ if (is_mac) {
|
||||
# Add the SwiftShader .dylibs in the Libraries directory of the Framework.
|
||||
bundle_data("electron_swiftshader_binaries") {
|
||||
sources = [
|
||||
"$root_out_dir/egl_intermediates/libswiftshader_libEGL.dylib",
|
||||
"$root_out_dir/egl_intermediates/libswiftshader_libGLESv2.dylib",
|
||||
"$root_out_dir/vk_intermediates/libvk_swiftshader.dylib",
|
||||
"$root_out_dir/vk_intermediates/vk_swiftshader_icd.json",
|
||||
]
|
||||
outputs = [ "{{bundle_contents_dir}}/Libraries/{{source_file_part}}" ]
|
||||
public_deps = [ "//ui/gl:swiftshader_vk_library_copy" ]
|
||||
public_deps = [
|
||||
"//ui/gl:swiftshader_egl_library_copy",
|
||||
"//ui/gl:swiftshader_vk_library_copy",
|
||||
]
|
||||
}
|
||||
}
|
||||
group("electron_angle_library") {
|
||||
@@ -949,10 +897,7 @@ if (is_mac) {
|
||||
assert(defined(invoker.helper_name_suffix))
|
||||
|
||||
output_name = electron_helper_name + invoker.helper_name_suffix
|
||||
deps = [
|
||||
":electron_framework+link",
|
||||
"//base/allocator:early_zone_registration_mac",
|
||||
]
|
||||
deps = [ ":electron_framework+link" ]
|
||||
if (!is_mas_build) {
|
||||
deps += [ "//sandbox/mac:seatbelt" ]
|
||||
}
|
||||
@@ -1060,14 +1005,14 @@ if (is_mac) {
|
||||
action("electron_app_lproj_dirs") {
|
||||
outputs = []
|
||||
|
||||
foreach(locale, locales_as_apple_outputs) {
|
||||
foreach(locale, locales_as_mac_outputs) {
|
||||
outputs += [ "$target_gen_dir/app_infoplist_strings/$locale.lproj" ]
|
||||
}
|
||||
script = "build/mac/make_locale_dirs.py"
|
||||
args = rebase_path(outputs)
|
||||
}
|
||||
|
||||
foreach(locale, locales_as_apple_outputs) {
|
||||
foreach(locale, locales_as_mac_outputs) {
|
||||
bundle_data("electron_app_strings_${locale}_bundle_data") {
|
||||
sources = [ "$target_gen_dir/app_infoplist_strings/$locale.lproj" ]
|
||||
outputs = [ "{{bundle_resources_dir}}/$locale.lproj" ]
|
||||
@@ -1076,7 +1021,7 @@ if (is_mac) {
|
||||
}
|
||||
group("electron_app_strings_bundle_data") {
|
||||
public_deps = []
|
||||
foreach(locale, locales_as_apple_outputs) {
|
||||
foreach(locale, locales_as_mac_outputs) {
|
||||
public_deps += [ ":electron_app_strings_${locale}_bundle_data" ]
|
||||
}
|
||||
}
|
||||
@@ -1105,6 +1050,7 @@ if (is_mac) {
|
||||
"shell/app/electron_main_mac.cc",
|
||||
"shell/app/uv_stdio_fix.cc",
|
||||
"shell/app/uv_stdio_fix.h",
|
||||
"shell/common/electron_constants.cc",
|
||||
]
|
||||
include_dirs = [ "." ]
|
||||
deps = [
|
||||
@@ -1112,7 +1058,6 @@ if (is_mac) {
|
||||
":electron_app_plist",
|
||||
":electron_app_resources",
|
||||
":electron_fuses",
|
||||
"//base/allocator:early_zone_registration_mac",
|
||||
"//electron/buildflags",
|
||||
]
|
||||
if (is_mas_build) {
|
||||
@@ -1156,18 +1101,21 @@ if (is_mac) {
|
||||
deps = [ ":electron_app" ]
|
||||
}
|
||||
|
||||
extract_symbols("egl_syms") {
|
||||
binary = "$root_out_dir/libEGL.dylib"
|
||||
extract_symbols("swiftshader_egl_syms") {
|
||||
binary = "$root_out_dir/libswiftshader_libEGL.dylib"
|
||||
symbol_dir = "$root_out_dir/breakpad_symbols"
|
||||
dsym_file = "$root_out_dir/libEGL.dylib.dSYM/Contents/Resources/DWARF/libEGL.dylib"
|
||||
deps = [ "//third_party/angle:libEGL" ]
|
||||
dsym_file = "$root_out_dir/libswiftshader_libEGL.dylib.dSYM/Contents/Resources/DWARF/libswiftshader_libEGL.dylib"
|
||||
deps =
|
||||
[ "//third_party/swiftshader/src/OpenGL/libEGL:swiftshader_libEGL" ]
|
||||
}
|
||||
|
||||
extract_symbols("gles_syms") {
|
||||
binary = "$root_out_dir/libGLESv2.dylib"
|
||||
extract_symbols("swiftshader_gles_syms") {
|
||||
binary = "$root_out_dir/libswiftshader_libGLESv2.dylib"
|
||||
symbol_dir = "$root_out_dir/breakpad_symbols"
|
||||
dsym_file = "$root_out_dir/libGLESv2.dylib.dSYM/Contents/Resources/DWARF/libGLESv2.dylib"
|
||||
deps = [ "//third_party/angle:libGLESv2" ]
|
||||
dsym_file = "$root_out_dir/libswiftshader_libGLESv2.dylib.dSYM/Contents/Resources/DWARF/libswiftshader_libGLESv2.dylib"
|
||||
deps = [
|
||||
"//third_party/swiftshader/src/OpenGL/libGLESv2:swiftshader_libGLESv2",
|
||||
]
|
||||
}
|
||||
|
||||
extract_symbols("crashpad_handler_syms") {
|
||||
@@ -1179,10 +1127,10 @@ if (is_mac) {
|
||||
|
||||
group("electron_symbols") {
|
||||
deps = [
|
||||
":egl_syms",
|
||||
":electron_app_syms",
|
||||
":electron_framework_syms",
|
||||
":gles_syms",
|
||||
":swiftshader_egl_syms",
|
||||
":swiftshader_gles_syms",
|
||||
]
|
||||
|
||||
if (!is_mas_build) {
|
||||
@@ -1225,7 +1173,6 @@ if (is_mac) {
|
||||
":default_app_asar",
|
||||
":electron_app_manifest",
|
||||
":electron_lib",
|
||||
":electron_win32_resources",
|
||||
":packed_resources",
|
||||
"//components/crash/core/app",
|
||||
"//content:sandbox_helper_win",
|
||||
@@ -1259,7 +1206,8 @@ if (is_mac) {
|
||||
|
||||
if (is_win) {
|
||||
sources += [
|
||||
"$target_gen_dir/win-resources/electron.rc",
|
||||
# TODO: we should be generating our .rc files more like how chrome does
|
||||
"shell/browser/resources/win/electron.rc",
|
||||
"shell/browser/resources/win/resource.h",
|
||||
]
|
||||
|
||||
@@ -1319,10 +1267,6 @@ if (is_mac) {
|
||||
if (!is_component_build && is_component_ffmpeg) {
|
||||
configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
deps += [ "//sandbox/linux:chrome_sandbox" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1341,23 +1285,27 @@ if (is_mac) {
|
||||
deps = [ ":electron_app" ]
|
||||
}
|
||||
|
||||
extract_symbols("egl_symbols") {
|
||||
binary = "$root_out_dir/libEGL$_target_shared_library_suffix"
|
||||
extract_symbols("swiftshader_egl_symbols") {
|
||||
binary = "$root_out_dir/swiftshader/libEGL$_target_shared_library_suffix"
|
||||
symbol_dir = "$root_out_dir/breakpad_symbols"
|
||||
deps = [ "//third_party/angle:libEGL" ]
|
||||
deps =
|
||||
[ "//third_party/swiftshader/src/OpenGL/libEGL:swiftshader_libEGL" ]
|
||||
}
|
||||
|
||||
extract_symbols("gles_symbols") {
|
||||
binary = "$root_out_dir/libGLESv2$_target_shared_library_suffix"
|
||||
extract_symbols("swiftshader_gles_symbols") {
|
||||
binary =
|
||||
"$root_out_dir/swiftshader/libGLESv2$_target_shared_library_suffix"
|
||||
symbol_dir = "$root_out_dir/breakpad_symbols"
|
||||
deps = [ "//third_party/angle:libGLESv2" ]
|
||||
deps = [
|
||||
"//third_party/swiftshader/src/OpenGL/libGLESv2:swiftshader_libGLESv2",
|
||||
]
|
||||
}
|
||||
|
||||
group("electron_symbols") {
|
||||
deps = [
|
||||
":egl_symbols",
|
||||
":electron_app_symbols",
|
||||
":gles_symbols",
|
||||
":swiftshader_egl_symbols",
|
||||
":swiftshader_gles_symbols",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1441,10 +1389,15 @@ group("licenses") {
|
||||
]
|
||||
}
|
||||
|
||||
copy("electron_version") {
|
||||
sources = [ "ELECTRON_VERSION" ]
|
||||
outputs = [ "$root_build_dir/version" ]
|
||||
}
|
||||
|
||||
dist_zip("electron_dist_zip") {
|
||||
data_deps = [
|
||||
":electron_app",
|
||||
":electron_version_file",
|
||||
":electron_version",
|
||||
":licenses",
|
||||
]
|
||||
if (is_linux) {
|
||||
|
||||
24
DEPS
@@ -1,12 +1,28 @@
|
||||
gclient_gn_args_from = 'src'
|
||||
gclient_gn_args_file = 'src/build/config/gclient_args.gni'
|
||||
gclient_gn_args = [
|
||||
'build_with_chromium',
|
||||
'checkout_android',
|
||||
'checkout_android_native_support',
|
||||
'checkout_libaom',
|
||||
'checkout_nacl',
|
||||
'checkout_pgo_profiles',
|
||||
'checkout_oculus_sdk',
|
||||
'checkout_openxr',
|
||||
'checkout_google_benchmark',
|
||||
'mac_xcode_version',
|
||||
'generate_location_tags',
|
||||
]
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'104.0.5112.124',
|
||||
'100.0.4896.75',
|
||||
'node_version':
|
||||
'v16.15.0',
|
||||
'v16.13.2',
|
||||
'nan_version':
|
||||
'16fa32231e2ccd89d2804b3f765319128b20c4ac',
|
||||
# The following commit hash of NAN is v2.14.2 with *only* changes to the
|
||||
# test suite. This should be updated to a specific tag when one becomes
|
||||
# available.
|
||||
'65b32af46e9d7fab2e4ff657751205b3865f4920',
|
||||
'squirrel.mac_version':
|
||||
'0e5d146ba13101a1302d59ea6e6e0b3cace4ae38',
|
||||
|
||||
|
||||
1
ELECTRON_VERSION
Normal file
@@ -0,0 +1 @@
|
||||
18.0.4
|
||||
35
README.md
@@ -34,17 +34,6 @@ For more installation options and troubleshooting tips, see
|
||||
[installation](docs/tutorial/installation.md). For info on how to manage Electron versions in your apps, see
|
||||
[Electron versioning](docs/tutorial/electron-versioning.md).
|
||||
|
||||
## Platform support
|
||||
|
||||
Each Electron release provides binaries for macOS, Windows, and Linux.
|
||||
|
||||
* macOS (High Sierra and up): Electron provides 64-bit Intel and ARM binaries for macOS. Apple Silicon support was added in Electron 11.
|
||||
* Windows (Windows 7 and up): Electron provides `ia32` (`x86`), `x64` (`amd64`), and `arm64` binaries for Windows. Windows on ARM support was added in Electron 5.0.8.
|
||||
* Linux: The prebuilt binaries of Electron are built on Ubuntu 20.04. They have also been verified to work on:
|
||||
* Ubuntu 14.04 and newer
|
||||
* Fedora 24 and newer
|
||||
* Debian 8 and newer
|
||||
|
||||
## Quick start & Electron Fiddle
|
||||
|
||||
Use [`Electron Fiddle`](https://github.com/electron/fiddle)
|
||||
@@ -65,10 +54,12 @@ npm start
|
||||
|
||||
## Resources for learning Electron
|
||||
|
||||
* [electronjs.org/docs](https://electronjs.org/docs) - All of Electron's documentation
|
||||
* [electron/fiddle](https://github.com/electron/fiddle) - A tool to build, run, and package small Electron experiments
|
||||
* [electron/electron-quick-start](https://github.com/electron/electron-quick-start) - A very basic starter Electron app
|
||||
* [electronjs.org/community#boilerplates](https://electronjs.org/community#boilerplates) - Sample starter apps created by the community
|
||||
- [electronjs.org/docs](https://electronjs.org/docs) - All of Electron's documentation
|
||||
- [electron/fiddle](https://github.com/electron/fiddle) - A tool to build, run, and package small Electron experiments
|
||||
- [electron/electron-quick-start](https://github.com/electron/electron-quick-start) - A very basic starter Electron app
|
||||
- [electronjs.org/community#boilerplates](https://electronjs.org/community#boilerplates) - Sample starter apps created by the community
|
||||
- [electron/simple-samples](https://github.com/electron/simple-samples) - Small applications with ideas for taking them further
|
||||
- [electron/electron-api-demos](https://github.com/electron/electron-api-demos) - An Electron app that teaches you how to use Electron
|
||||
|
||||
## Programmatic usage
|
||||
|
||||
@@ -89,15 +80,11 @@ const child = proc.spawn(electron)
|
||||
|
||||
### Mirrors
|
||||
|
||||
* [China](https://npmmirror.com/mirrors/electron/)
|
||||
- [China](https://npmmirror.com/mirrors/electron)
|
||||
|
||||
See the [Advanced Installation Instructions](https://www.electronjs.org/docs/latest/tutorial/installation#mirror) to learn how to use a custom mirror.
|
||||
## Documentation Translations
|
||||
|
||||
## Documentation translations
|
||||
|
||||
We crowdsource translations for our documentation via [Crowdin](https://crowdin.com/project/electron).
|
||||
We currently accept translations for Chinese (Simplified), French, German, Japanese, Portuguese,
|
||||
Russian, and Spanish.
|
||||
Find documentation translations in [electron/i18n](https://github.com/electron/i18n).
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -106,10 +93,10 @@ If you are interested in reporting/fixing issues and contributing directly to th
|
||||
## Community
|
||||
|
||||
Info on reporting bugs, getting help, finding third-party tools and sample apps,
|
||||
and more can be found on the [Community page](https://www.electronjs.org/community).
|
||||
and more can be found in the [support document](docs/tutorial/support.md#finding-support).
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/electron/electron/blob/main/LICENSE)
|
||||
|
||||
When using Electron logos, make sure to follow [OpenJS Foundation Trademark Policy](https://openjsf.org/wp-content/uploads/sites/84/2021/01/OpenJS-Foundation-Trademark-Policy-2021-01-12.docx.pdf).
|
||||
When using the Electron or other GitHub logos, be sure to follow the [GitHub logo guidelines](https://github.com/logos).
|
||||
|
||||
468
appveyor.yml
@@ -3,7 +3,7 @@
|
||||
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
|
||||
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
|
||||
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_cpu
|
||||
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordingly
|
||||
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordningly
|
||||
# if you pass a custom value for 'target_cpu'.
|
||||
# - "ELECTRON_RELEASE" Set it to '1' upload binaries on success.
|
||||
# - "NPM_CONFIG_ARCH" E.g. 'x86'. Is used to build native Node.js modules.
|
||||
@@ -11,8 +11,8 @@
|
||||
# - "TARGET_ARCH" Choose from {'ia32', 'x64', 'arm', 'arm64', 'mips64el'}.
|
||||
# Is used in some publishing scripts, but does NOT affect the Electron binary.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "NPM_CONFIG_ARCH" value.
|
||||
# - "UPLOAD_TO_STORAGE" Set it to '1' upload a release to the Azure bucket.
|
||||
# Otherwise the release will be uploaded to the GitHub Releases.
|
||||
# - "UPLOAD_TO_S3" Set it to '1' upload a release to the S3 bucket.
|
||||
# Otherwise the release will be uploaded to the Github Releases.
|
||||
# (The value is only checked if "ELECTRON_RELEASE" is defined.)
|
||||
#
|
||||
# The publishing scripts expect access tokens to be defined as env vars,
|
||||
@@ -23,9 +23,13 @@
|
||||
# https://www.appveyor.com/docs/build-configuration/#secure-variables
|
||||
# https://www.appveyor.com/docs/build-configuration/#custom-environment-variables
|
||||
|
||||
# Uncomment these lines to enable RDP
|
||||
#on_finish:
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electron-16-core
|
||||
image: vs2019bt-16.16.11
|
||||
image: vs2019bt-16.6.2
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\electron\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -34,278 +38,212 @@ environment:
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
|
||||
matrix:
|
||||
|
||||
- job_name: Build
|
||||
|
||||
- job_name: Test
|
||||
job_depends_on: Build
|
||||
|
||||
clone_folder: C:\projects\src\electron
|
||||
|
||||
# the first failed job cancels other jobs and fails entire build
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
for:
|
||||
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- job_name: Build
|
||||
|
||||
init:
|
||||
- ps: >-
|
||||
if(($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -split "/")[0] -eq ($env:APPVEYOR_REPO_NAME -split "/")[0]) {
|
||||
Write-warning "Skipping PR build for branch"; Exit-AppveyorBuild
|
||||
}
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
notifications:
|
||||
- provider: Webhook
|
||||
url: https://electron-mission-control.herokuapp.com/rest/appveyor-hook
|
||||
method: POST
|
||||
headers:
|
||||
x-mission-control-secret:
|
||||
secure: 90BLVPcqhJPG7d24v0q/RRray6W3wDQ8uVQlQjOHaBWkw1i8FoA1lsjr2C/v1dVok+tS2Pi6KxDctPUkwIb4T27u4RhvmcPzQhVpfwVJAG9oNtq+yKN7vzHfg7k/pojEzVdJpQLzeJGcSrZu7VY39Q==
|
||||
on_build_success: false
|
||||
on_build_failure: true
|
||||
on_build_status_changed: false
|
||||
build_script:
|
||||
- ps: >-
|
||||
if(($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -split "/")[0] -eq ($env:APPVEYOR_REPO_NAME -split "/")[0]) {
|
||||
Write-warning "Skipping PR build for branch"; Exit-AppveyorBuild
|
||||
} else {
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-warning "Skipping tests for doc only change"; Exit-AppveyorBuild
|
||||
|
||||
$result = node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
|
||||
Write-Output $result
|
||||
if ($result.ExitCode -eq 0) {
|
||||
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
|
||||
}
|
||||
$global:LASTEXITCODE = 0
|
||||
- cd ..
|
||||
- ps: Write-Host "Building $env:GN_CONFIG build"
|
||||
- git config --global core.longpaths true
|
||||
- update_depot_tools.bat
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..\..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
}
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
$env:NINJA_STATUS="[%r processes, %f/%t @ %o/s : %es] "
|
||||
}
|
||||
- >-
|
||||
gclient config
|
||||
--name "src\electron"
|
||||
--unmanaged
|
||||
%GCLIENT_EXTRA_ARGS%
|
||||
"https://github.com/electron/electron"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
$env:RUN_GCLIENT_SYNC="true"
|
||||
}
|
||||
- echo "Building $env:GN_CONFIG build"
|
||||
- git config --global core.longpaths true
|
||||
- cd ..
|
||||
- mkdir src
|
||||
- update_depot_tools.bat
|
||||
- ps: Move-Item $env:APPVEYOR_BUILD_FOLDER -Destination src\electron
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
cd src\electron
|
||||
node script\generate-deps-hash.js
|
||||
$depshash = Get-Content .\.depshash -Raw
|
||||
$zipfile = "Z:\$depshash.7z"
|
||||
cd ..\..
|
||||
if (Test-Path -Path $zipfile) {
|
||||
# file exists, unzip and then gclient sync
|
||||
7z x -y $zipfile -mmt=14 -aoa
|
||||
if (-not (Test-Path -Path "src\buildtools")) {
|
||||
# the zip file must be corrupt - resync
|
||||
$env:RUN_GCLIENT_SYNC="true"
|
||||
if ($env:TARGET_ARCH -ne 'ia32') {
|
||||
# only save on x64/woa to avoid contention saving
|
||||
$env:SAVE_GCLIENT_SRC="true"
|
||||
}
|
||||
} else {
|
||||
# update angle
|
||||
cd src\third_party\angle
|
||||
git remote set-url origin https://chromium.googlesource.com/angle/angle.git
|
||||
git fetch
|
||||
cd ..\..\..
|
||||
}
|
||||
} else {
|
||||
# file does not exist, gclient sync, then zip
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
}
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
$env:NINJA_STATUS="[%r processes, %f/%t @ %o/s : %es] "
|
||||
}
|
||||
- >-
|
||||
gclient config
|
||||
--name "src\electron"
|
||||
--unmanaged
|
||||
%GCLIENT_EXTRA_ARGS%
|
||||
"https://github.com/electron/electron"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
$env:RUN_GCLIENT_SYNC="true"
|
||||
} else {
|
||||
cd src\electron
|
||||
node script\generate-deps-hash.js
|
||||
$depshash = Get-Content .\.depshash -Raw
|
||||
$zipfile = "Z:\$depshash.7z"
|
||||
cd ..\..
|
||||
if (Test-Path -Path $zipfile) {
|
||||
# file exists, unzip and then gclient sync
|
||||
7z x -y $zipfile -mmt=30 -aoa
|
||||
if (-not (Test-Path -Path "src\buildtools")) {
|
||||
# the zip file must be corrupt - resync
|
||||
$env:RUN_GCLIENT_SYNC="true"
|
||||
if ($env:TARGET_ARCH -ne 'ia32') {
|
||||
# only save on x64/woa to avoid contention saving
|
||||
$env:SAVE_GCLIENT_SRC="true"
|
||||
}
|
||||
} else {
|
||||
# update angle
|
||||
cd src\third_party\angle
|
||||
git remote set-url origin https://chromium.googlesource.com/angle/angle.git
|
||||
git fetch
|
||||
cd ..\..\..
|
||||
}
|
||||
} else {
|
||||
# file does not exist, gclient sync, then zip
|
||||
$env:RUN_GCLIENT_SYNC="true"
|
||||
if ($env:TARGET_ARCH -ne 'ia32') {
|
||||
# only save on x64/woa to avoid contention saving
|
||||
$env:SAVE_GCLIENT_SRC="true"
|
||||
}
|
||||
}
|
||||
- if "%RUN_GCLIENT_SYNC%"=="true" ( gclient sync )
|
||||
- ps: >-
|
||||
if ($env:SAVE_GCLIENT_SRC -eq 'true') {
|
||||
# archive current source for future use
|
||||
# only run on x64/woa to avoid contention saving
|
||||
$(7z a $zipfile src -xr!android_webview -xr!electron -xr'!*\.git' -xr!third_party\blink\web_tests -xr!third_party\blink\perf_tests -slp -t7z -mmt=30)
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-warning "Could not save source to shared drive; continuing anyway"
|
||||
}
|
||||
# build time generation of file gen/angle/angle_commit.h depends on
|
||||
# third_party/angle/.git
|
||||
# https://chromium-review.googlesource.com/c/angle/angle/+/2074924
|
||||
$(7z a $zipfile src\third_party\angle\.git)
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-warning "Failed to add third_party\angle\.git; continuing anyway"
|
||||
}
|
||||
# build time generation of file dawn/common/Version_autogen.h depends on third_party/dawn/.git/HEAD
|
||||
# https://dawn-review.googlesource.com/c/dawn/+/83901
|
||||
$(7z a $zipfile src\third_party\dawn\.git)
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-warning "Failed to add third_party\dawn\.git; continuing anyway"
|
||||
}
|
||||
}
|
||||
- if "%RUN_GCLIENT_SYNC%"=="true" ( gclient sync )
|
||||
- ps: >-
|
||||
if ($env:SAVE_GCLIENT_SRC -eq 'true') {
|
||||
# archive current source for future use
|
||||
# only run on x64/woa to avoid contention saving
|
||||
$(7z a $zipfile src -xr!android_webview -xr!electron -xr'!*\.git' -xr!third_party\WebKit\LayoutTests! -xr!third_party\blink\web_tests -xr!third_party\blink\perf_tests -slp -t7z -mmt=30)
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-warning "Could not save source to shared drive; continuing anyway"
|
||||
}
|
||||
- cd src
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron/shell/common/api:mojo
|
||||
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- ninja -C out/Default electron:electron_dist_zip
|
||||
- ninja -C out/Default shell_browser_ui_unittests
|
||||
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
|
||||
- ninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- cd out\Default
|
||||
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
|
||||
- cd ..\..
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default third_party/electron_node:headers
|
||||
- python %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
- 7z a node_headers.zip out\Default\gen\node_headers
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
# build time generation of file gen/angle/angle_commit.h depends on
|
||||
# third_party/angle/.git
|
||||
# https://chromium-review.googlesource.com/c/angle/angle/+/2074924
|
||||
$(7z a $zipfile src\third_party\angle\.git)
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-warning "Failed to add third_party\angle\.git; continuing anyway"
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
python3 electron\script\zip-symbols.py
|
||||
appveyor-retry appveyor PushArtifact out/Default/symbols.zip
|
||||
}
|
||||
- cd src
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron/shell/common/api:mojo
|
||||
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- ninja -C out/Default electron:electron_dist_zip
|
||||
- ninja -C out/Default shell_browser_ui_unittests
|
||||
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
|
||||
- ninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- cd out\Default
|
||||
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
|
||||
- cd ..\..
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default third_party/electron_node:headers
|
||||
- python %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- python electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
- appveyor PushArtifact out/Default/windows_toolchain_profile.json
|
||||
- appveyor PushArtifact out/Default/dist.zip
|
||||
- appveyor PushArtifact out/Default/shell_browser_ui_unittests.exe
|
||||
- appveyor PushArtifact out/Default/chromedriver.zip
|
||||
- appveyor PushArtifact out/ffmpeg/ffmpeg.zip
|
||||
- 7z a node_headers.zip out\Default\gen\node_headers
|
||||
- appveyor PushArtifact node_headers.zip
|
||||
- appveyor PushArtifact out/Default/mksnapshot.zip
|
||||
- appveyor PushArtifact out/Default/hunspell_dictionaries.zip
|
||||
- appveyor PushArtifact out/Default/electron.lib
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
python electron\script\zip-symbols.py
|
||||
appveyor-retry appveyor PushArtifact out/Default/symbols.zip
|
||||
} else {
|
||||
# It's useful to have pdb files when debugging testing builds that are
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
}
|
||||
- python electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
test_script:
|
||||
# Workaround for https://github.com/appveyor/ci/issues/2420
|
||||
- set "PATH=%PATH%;C:\Program Files\Git\mingw64\libexec\git-core"
|
||||
- ps: >-
|
||||
if ((-Not (Test-Path Env:\TEST_WOA)) -And (-Not (Test-Path Env:\ELECTRON_RELEASE)) -And ($env:GN_CONFIG -in "testing", "release")) {
|
||||
$env:RUN_TESTS="true"
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:RUN_TESTS -eq 'true') {
|
||||
New-Item .\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path .\out\Default\electron.lib -destination .\out\Default\gen\node_headers\Release\node.lib
|
||||
} else {
|
||||
echo "Skipping tests for $env:GN_CONFIG build"
|
||||
}
|
||||
- cd electron
|
||||
# CalculateNativeWinOcclusion is disabled due to https://bugs.chromium.org/p/chromium/issues/detail?id=1139022
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running main test suite & node script/yarn test -- --trace-uncaught --runners=main --enable-logging=file --log-file=%cd%\electron.log --disable-features=CalculateNativeWinOcclusion )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running remote test suite & node script/yarn test -- --trace-uncaught --runners=remote --runTestFilesSeperately --enable-logging=file --log-file=%cd%\electron.log --disable-features=CalculateNativeWinOcclusion )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running native test suite & node script/yarn test -- --trace-uncaught --runners=native --enable-logging=file --log-file=%cd%\electron.log --disable-features=CalculateNativeWinOcclusion )
|
||||
- cd ..
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
|
||||
- echo "About to verify mksnapshot"
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd% )
|
||||
- echo "Done verifying mksnapshot"
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying chromedriver & python electron\script\verify-chromedriver.py --build-dir out\Default --source-root %cd% )
|
||||
- echo "Done verifying chromedriver"
|
||||
- if exist %cd%\electron.log ( appveyor-retry appveyor PushArtifact %cd%\electron.log )
|
||||
deploy_script:
|
||||
- cd electron
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\UPLOAD_TO_S3) {
|
||||
Write-Output "Uploading Electron release distribution to s3"
|
||||
& python script\release\uploaders\upload.py --verbose --upload_to_s3
|
||||
} else {
|
||||
# It's useful to have pdb files when debugging testing builds that are
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
|
||||
deploy_script:
|
||||
- cd electron
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\UPLOAD_TO_STORAGE) {
|
||||
Write-Output "Uploading Electron release distribution to azure"
|
||||
& python3 script\release\uploaders\upload.py --verbose --upload_to_storage
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python3 script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
} elseif (Test-Path Env:\TEST_WOA) {
|
||||
node script/release/ci-release-build.js --job=electron-woa-testing --ci=GHA --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH
|
||||
}
|
||||
on_finish:
|
||||
# Uncomment this lines to enable RDP
|
||||
#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- cd C:\projects\src
|
||||
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
|
||||
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
|
||||
- if exist out\Default\shell_browser_ui_unittests.exe (appveyor-retry appveyor PushArtifact out\Default\shell_browser_ui_unittests.exe)
|
||||
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
|
||||
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
|
||||
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
|
||||
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
|
||||
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
- ps: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
}
|
||||
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- job_name: Test
|
||||
|
||||
init:
|
||||
- ps: |
|
||||
if ($env:RUN_TESTS -ne 'true') {
|
||||
Write-warning "Skipping tests for $env:APPVEYOR_PROJECT_NAME"; Exit-AppveyorBuild
|
||||
}
|
||||
if(($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -split "/")[0] -eq ($env:APPVEYOR_REPO_NAME -split "/")[0]) {
|
||||
Write-warning "Skipping PR build for branch"; Exit-AppveyorBuild
|
||||
}
|
||||
build_script:
|
||||
- ps: |
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-warning "Skipping tests for doc only change"; Exit-AppveyorBuild
|
||||
}
|
||||
$global:LASTEXITCODE = 0
|
||||
- ps: |
|
||||
cd ..
|
||||
mkdir out\Default
|
||||
cd ..
|
||||
# Download build artifacts
|
||||
$apiUrl = 'https://ci.appveyor.com/api'
|
||||
$build_info = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/builds/$env:APPVEYOR_BUILD_ID"
|
||||
$artifacts_to_download = @('dist.zip','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib')
|
||||
foreach ($job in $build_info.build.jobs) {
|
||||
if ($job.name -eq "Build") {
|
||||
$jobId = $job.jobId
|
||||
foreach($artifact_name in $artifacts_to_download) {
|
||||
if ($artifact_name -eq 'shell_browser_ui_unittests.exe' -Or $artifact_name -eq 'electron.lib') {
|
||||
$outfile = "src\out\Default\$artifact_name"
|
||||
} else {
|
||||
$outfile = $artifact_name
|
||||
}
|
||||
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/$artifact_name" -OutFile $outfile
|
||||
}
|
||||
}
|
||||
}
|
||||
- ps: |
|
||||
$out_default_zips = @('dist.zip','chromedriver.zip','mksnapshot.zip')
|
||||
foreach($zip_name in $out_default_zips) {
|
||||
7z x -y -osrc\out\Default $zip_name
|
||||
}
|
||||
- ps: 7z x -y -osrc\out\ffmpeg ffmpeg.zip
|
||||
- ps: 7z x -y -osrc node_headers.zip
|
||||
|
||||
test_script:
|
||||
# Workaround for https://github.com/appveyor/ci/issues/2420
|
||||
- set "PATH=%PATH%;C:\Program Files\Git\mingw64\libexec\git-core"
|
||||
- ps: |
|
||||
cd src
|
||||
New-Item .\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path .\out\Default\electron.lib -destination .\out\Default\gen\node_headers\Release\node.lib
|
||||
- cd electron
|
||||
- echo Running main test suite & node script/yarn test -- --trace-uncaught --runners=main --enable-logging=file --log-file=%cd%\electron.log
|
||||
- echo Running native test suite & node script/yarn test -- --trace-uncaught --runners=native --enable-logging=file --log-file=%cd%\electron.log
|
||||
- cd ..
|
||||
- echo Verifying non proprietary ffmpeg & python3 electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
|
||||
- echo "About to verify mksnapshot"
|
||||
- echo Verifying mksnapshot & python3 electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd%
|
||||
- echo "Done verifying mksnapshot"
|
||||
- echo Verifying chromedriver & python3 electron\script\verify-chromedriver.py --build-dir out\Default --source-root %cd%
|
||||
- echo "Done verifying chromedriver"
|
||||
|
||||
on_finish:
|
||||
- if exist electron\electron.log ( appveyor-retry appveyor PushArtifact electron\electron.log )
|
||||
} elseif (Test-Path Env:\TEST_WOA) {
|
||||
node script/release/ci-release-build.js --job=electron-woa-testing --ci=VSTS --armTest --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH
|
||||
}
|
||||
on_finish:
|
||||
- if exist src\electron\electron.log ( appveyor-retry appveyor PushArtifact src\electron\electron.log )
|
||||
|
||||
121
azure-pipelines-arm.yml
Normal file
@@ -0,0 +1,121 @@
|
||||
steps:
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy Files to: src/electron'
|
||||
inputs:
|
||||
TargetFolder: src/electron
|
||||
|
||||
- bash: |
|
||||
cd src/electron
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
displayName: 'Yarn install'
|
||||
|
||||
- bash: |
|
||||
export ZIP_DEST=$PWD/src/out/Default
|
||||
echo "##vso[task.setvariable variable=ZIP_DEST]$ZIP_DEST"
|
||||
mkdir -p $ZIP_DEST
|
||||
cd src/electron
|
||||
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=dist.zip --dest=$ZIP_DEST
|
||||
cd $ZIP_DEST
|
||||
unzip -o dist.zip
|
||||
xattr -cr Electron.app
|
||||
displayName: 'Download and unzip dist files for test'
|
||||
env:
|
||||
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
|
||||
|
||||
- bash: |
|
||||
export FFMPEG_ZIP_DEST=$PWD/src/out/ffmpeg
|
||||
mkdir -p $FFMPEG_ZIP_DEST
|
||||
cd src/electron
|
||||
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=ffmpeg.zip --dest=$FFMPEG_ZIP_DEST
|
||||
cd $FFMPEG_ZIP_DEST
|
||||
unzip -o ffmpeg.zip
|
||||
displayName: 'Download and unzip ffmpeg for test'
|
||||
env:
|
||||
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
|
||||
|
||||
- bash: |
|
||||
export NODE_HEADERS_DEST=$PWD/src/out/Default/gen
|
||||
mkdir -p $NODE_HEADERS_DEST
|
||||
cd src/electron
|
||||
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=node_headers.tar.gz --dest=$NODE_HEADERS_DEST
|
||||
cd $NODE_HEADERS_DEST
|
||||
tar xzf node_headers.tar.gz
|
||||
displayName: 'Download and untar node header files for test'
|
||||
env:
|
||||
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
|
||||
|
||||
- bash: |
|
||||
export CROSS_ARCH_SNAPSHOTS=$PWD/src/out/Default/cross-arch-snapshots
|
||||
mkdir -p $CROSS_ARCH_SNAPSHOTS
|
||||
cd src/electron
|
||||
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=cross-arch-snapshots/snapshot_blob.bin --dest=$CROSS_ARCH_SNAPSHOTS
|
||||
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=cross-arch-snapshots/v8_context_snapshot.arm64.bin --dest=$CROSS_ARCH_SNAPSHOTS
|
||||
displayName: 'Download cross arch snapshot files'
|
||||
env:
|
||||
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
|
||||
|
||||
- bash: |
|
||||
cd src
|
||||
export ELECTRON_OUT_DIR=Default
|
||||
export npm_config_arch=arm64
|
||||
(cd electron && node script/yarn test --enable-logging --runners main)
|
||||
displayName: 'Run Electron main tests'
|
||||
timeoutInMinutes: 20
|
||||
env:
|
||||
ELECTRON_DISABLE_SECURITY_WARNINGS: 1
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
|
||||
- bash: |
|
||||
cd src
|
||||
export ELECTRON_OUT_DIR=Default
|
||||
export npm_config_arch=arm64
|
||||
(cd electron && node script/yarn test --enable-logging --runners remote)
|
||||
displayName: 'Run Electron remote tests'
|
||||
timeoutInMinutes: 20
|
||||
condition: succeededOrFailed()
|
||||
env:
|
||||
ELECTRON_DISABLE_SECURITY_WARNINGS: 1
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
|
||||
- bash: |
|
||||
cd src
|
||||
python electron/script/verify-ffmpeg.py --source-root "$PWD" --build-dir out/Default --ffmpeg-path out/ffmpeg
|
||||
displayName: Verify non proprietary ffmpeg
|
||||
timeoutInMinutes: 5
|
||||
condition: succeededOrFailed()
|
||||
env:
|
||||
TARGET_ARCH: arm64
|
||||
|
||||
- bash: |
|
||||
cd src
|
||||
echo Verify cross arch snapshot
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --snapshot-files-dir $PWD/out/Default/cross-arch-snapshots
|
||||
displayName: Verify cross arch snapshot
|
||||
timeoutInMinutes: 5
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish Test Results'
|
||||
inputs:
|
||||
testResultsFiles: '*.xml'
|
||||
|
||||
searchFolder: '$(System.DefaultWorkingDirectory)/src/junit/'
|
||||
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- bash: killall Electron || echo "No Electron processes left running"
|
||||
displayName: 'Kill processes left running from last test run'
|
||||
condition: always()
|
||||
|
||||
- bash: |
|
||||
rm -rf ~/Library/Application\ Support/Electron*
|
||||
rm -rf ~/Library/Application\ Support/electron*
|
||||
displayName: 'Delete user app data directories'
|
||||
condition: always()
|
||||
|
||||
- task: mspremier.PostBuildCleanup.PostBuildCleanup-task.PostBuildCleanup@3
|
||||
displayName: 'Clean Agent Directories'
|
||||
|
||||
condition: always()
|
||||
130
azure-pipelines-woa.yml
Normal file
@@ -0,0 +1,130 @@
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
path: src\electron
|
||||
|
||||
- script: |
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
displayName: 'Yarn install'
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$pwd\dist.zip"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/dist.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -o$(Pipeline.Workspace)\src\out\Default -y $localArtifactPath
|
||||
displayName: 'Download and extract dist.zip for test'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$(Pipeline.Workspace)\src\out\Default\shell_browser_ui_unittests.exe"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/shell_browser_ui_unittests.exe"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
displayName: 'Download and extract native test executables for test'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$pwd\ffmpeg.zip"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/ffmpeg.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -o$(Pipeline.Workspace)\src\out\ffmpeg $localArtifactPath
|
||||
displayName: 'Download and extract ffmpeg.zip for test'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$(Pipeline.Workspace)\src\node_headers.zip"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/node_headers.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
cd $(Pipeline.Workspace)\src
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y node_headers.zip
|
||||
displayName: 'Download node headers for test'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
$localArtifactPath = "$(Pipeline.Workspace)\src\out\Default\electron.lib"
|
||||
$serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/electron.lib"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
displayName: 'Download electron.lib for test'
|
||||
env:
|
||||
APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
# Uncomment the following block if pdb files are needed to debug issues
|
||||
# - powershell: |
|
||||
# try {
|
||||
# $localArtifactPath = "$(Pipeline.Workspace)\src\pdb.zip"
|
||||
# $serverArtifactPath = "$env:APPVEYOR_URL/buildjobs/$env:APPVEYOR_JOB_ID/artifacts/pdb.zip"
|
||||
# Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer $env:APPVEYOR_TOKEN" }
|
||||
# cd $(Pipeline.Workspace)\src
|
||||
# & "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y pdb.zip
|
||||
# } catch {
|
||||
# Write-Host "There was an exception encountered while downloading pdb files:" $_.Exception.Message
|
||||
# } finally {
|
||||
# $global:LASTEXITCODE = 0
|
||||
# }
|
||||
# displayName: 'Download pdb files for detailed stacktraces'
|
||||
# env:
|
||||
# APPVEYOR_TOKEN: $(APPVEYOR_TOKEN)
|
||||
|
||||
- powershell: |
|
||||
New-Item $(Pipeline.Workspace)\src\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path $(Pipeline.Workspace)\src\out\Default\electron.lib -destination $(Pipeline.Workspace)\src\out\Default\gen\node_headers\Release\node.lib
|
||||
displayName: 'Setup node headers'
|
||||
|
||||
- script: |
|
||||
cd $(Pipeline.Workspace)\src
|
||||
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
node script/yarn test --runners=main --enable-logging --disable-features=CalculateNativeWinOcclusion
|
||||
displayName: 'Run Electron Main process tests'
|
||||
env:
|
||||
ELECTRON_ENABLE_STACK_DUMPING: true
|
||||
ELECTRON_OUT_DIR: Default
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
|
||||
- script: |
|
||||
cd $(Pipeline.Workspace)\src
|
||||
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
node script/yarn test --runners=remote --enable-logging --disable-features=CalculateNativeWinOcclusion
|
||||
displayName: 'Run Electron Remote based tests'
|
||||
env:
|
||||
ELECTRON_OUT_DIR: Default
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish Test Results'
|
||||
inputs:
|
||||
testResultsFiles: '*.xml'
|
||||
searchFolder: '$(Pipeline.Workspace)/src/junit/'
|
||||
condition: always()
|
||||
|
||||
- script: |
|
||||
cd $(Pipeline.Workspace)\src
|
||||
echo "Verifying non proprietary ffmpeg"
|
||||
python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
|
||||
displayName: 'Verify ffmpeg'
|
||||
|
||||
- powershell: |
|
||||
Get-Process | Where Name –Like "electron*" | Stop-Process
|
||||
Get-Process | Where Name –Like "msedge*" | Stop-Process
|
||||
displayName: 'Kill processes left running from last test run'
|
||||
condition: always()
|
||||
|
||||
- powershell: |
|
||||
Remove-Item -path $env:APPDATA/Electron* -Recurse -Force -ErrorAction Ignore
|
||||
displayName: 'Delete user app data directories'
|
||||
condition: always()
|
||||
@@ -2,7 +2,7 @@ is_electron_build = true
|
||||
root_extra_deps = [ "//electron" ]
|
||||
|
||||
# Registry of NMVs --> https://github.com/nodejs/node/blob/master/doc/abi_version_registry.json
|
||||
node_module_version = 107
|
||||
node_module_version = 103
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_embedder_string = "-electron.0"
|
||||
@@ -21,29 +21,20 @@ proprietary_codecs = true
|
||||
ffmpeg_branding = "Chrome"
|
||||
|
||||
enable_basic_printing = true
|
||||
|
||||
# Removes DLLs from the build, which are only meant to be used for Chromium development.
|
||||
# See https://github.com/electron/electron/pull/17985
|
||||
angle_enable_vulkan_validation_layers = false
|
||||
dawn_enable_vulkan_validation_layers = false
|
||||
|
||||
# This breaks native node modules
|
||||
libcxx_abi_unstable = false
|
||||
|
||||
# These are disabled because they cause the zip manifest to differ between
|
||||
# testing and release builds.
|
||||
# See https://chromium-review.googlesource.com/c/chromium/src/+/2774898.
|
||||
enable_pseudolocales = false
|
||||
|
||||
is_cfi = false
|
||||
|
||||
# Make application name configurable at runtime for cookie crypto
|
||||
allow_runtime_configurable_key_storage = true
|
||||
|
||||
# CET shadow stack is incompatible with v8, until v8 is CET compliant
|
||||
# enabling this flag causes main process crashes where CET is enabled
|
||||
# Ref: https://source.chromium.org/chromium/chromium/src/+/45fba672185aae233e75d6ddc81ea1e0b30db050:v8/BUILD.gn;l=357
|
||||
enable_cet_shadow_stack = false
|
||||
|
||||
# For similar reasons, disable CFI, which is not well supported in V8.
|
||||
# Chromium doesn't have any problems with this because they do not run
|
||||
# V8 in the browser process.
|
||||
# Ref: https://source.chromium.org/chromium/chromium/src/+/45fba672185aae233e75d6ddc81ea1e0b30db050:v8/BUILD.gn;l=281
|
||||
is_cfi = false
|
||||
|
||||
v8_enable_sandboxed_pointers = false
|
||||
|
||||
@@ -24,11 +24,7 @@ template("extract_symbols") {
|
||||
assert(defined(invoker.binary), "Need binary to dump")
|
||||
assert(defined(invoker.symbol_dir), "Need directory for symbol output")
|
||||
|
||||
if (host_os == "win" && target_cpu == "x86") {
|
||||
dump_syms_label = "//third_party/breakpad:dump_syms(//build/toolchain/win:win_clang_x64)"
|
||||
} else {
|
||||
dump_syms_label = "//third_party/breakpad:dump_syms($host_toolchain)"
|
||||
}
|
||||
dump_syms_label = "//third_party/breakpad:dump_syms($host_toolchain)"
|
||||
dump_syms_binary = get_label_info(dump_syms_label, "root_out_dir") +
|
||||
"/dump_syms$_host_executable_suffix"
|
||||
|
||||
|
||||
@@ -7,6 +7,5 @@
|
||||
"node_options": "1",
|
||||
"node_cli_inspect": "1",
|
||||
"embedded_asar_integrity_validation": "0",
|
||||
"only_load_app_from_asar": "0",
|
||||
"load_browser_process_specific_v8_snapshot": "0"
|
||||
"only_load_app_from_asar": "0"
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
$full_version
|
||||
@@ -19,6 +19,7 @@ buildflag_header("buildflags") {
|
||||
"ENABLE_ELECTRON_EXTENSIONS=$enable_electron_extensions",
|
||||
"ENABLE_BUILTIN_SPELLCHECKER=$enable_builtin_spellchecker",
|
||||
"ENABLE_PICTURE_IN_PICTURE=$enable_picture_in_picture",
|
||||
"ENABLE_WIN_DARK_MODE_WINDOW_UI=$enable_win_dark_mode_window_ui",
|
||||
"OVERRIDE_LOCATION_PROVIDER=$enable_fake_location_provider",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -31,4 +31,7 @@ declare_args() {
|
||||
|
||||
# Enable Spellchecker support
|
||||
enable_builtin_spellchecker = true
|
||||
|
||||
# Undocumented Windows dark mode API
|
||||
enable_win_dark_mode_window_ui = false
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import("//build/config/ozone.gni")
|
||||
import("//build/config/ui.gni")
|
||||
import("//components/spellcheck/spellcheck_build_features.gni")
|
||||
import("//electron/buildflags/buildflags.gni")
|
||||
import("//ppapi/buildflags/buildflags.gni")
|
||||
import("//printing/buildflags/buildflags.gni")
|
||||
import("//third_party/widevine/cdm/widevine.gni")
|
||||
|
||||
@@ -56,14 +55,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/process_singleton.h",
|
||||
"//chrome/browser/process_singleton_internal.cc",
|
||||
"//chrome/browser/process_singleton_internal.h",
|
||||
"//chrome/browser/themes/browser_theme_pack.cc",
|
||||
"//chrome/browser/themes/browser_theme_pack.h",
|
||||
"//chrome/browser/themes/custom_theme_supplier.cc",
|
||||
"//chrome/browser/themes/custom_theme_supplier.h",
|
||||
"//chrome/browser/themes/theme_properties.cc",
|
||||
"//chrome/browser/themes/theme_properties.h",
|
||||
"//chrome/browser/ui/color/chrome_color_mixers.cc",
|
||||
"//chrome/browser/ui/color/chrome_color_mixers.h",
|
||||
"//chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.cc",
|
||||
"//chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h",
|
||||
"//chrome/browser/ui/exclusive_access/exclusive_access_controller_base.cc",
|
||||
@@ -78,11 +69,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/ui/exclusive_access/keyboard_lock_controller.h",
|
||||
"//chrome/browser/ui/exclusive_access/mouse_lock_controller.cc",
|
||||
"//chrome/browser/ui/exclusive_access/mouse_lock_controller.h",
|
||||
"//chrome/browser/ui/frame/window_frame_util.cc",
|
||||
"//chrome/browser/ui/frame/window_frame_util.h",
|
||||
"//chrome/browser/ui/native_window_tracker.h",
|
||||
"//chrome/browser/ui/ui_features.cc",
|
||||
"//chrome/browser/ui/ui_features.h",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper.cc",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper.h",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view.cc",
|
||||
@@ -102,8 +88,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/icon_loader_mac.mm",
|
||||
"//chrome/browser/media/webrtc/system_media_capture_permissions_mac.h",
|
||||
"//chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm",
|
||||
"//chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.h",
|
||||
"//chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.mm",
|
||||
"//chrome/browser/media/webrtc/window_icon_util_mac.mm",
|
||||
"//chrome/browser/process_singleton_mac.mm",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.h",
|
||||
@@ -122,8 +106,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/ui/view_ids.h",
|
||||
"//chrome/browser/win/chrome_process_finder.cc",
|
||||
"//chrome/browser/win/chrome_process_finder.h",
|
||||
"//chrome/browser/win/titlebar_config.cc",
|
||||
"//chrome/browser/win/titlebar_config.h",
|
||||
"//chrome/browser/win/titlebar_config.h",
|
||||
"//chrome/child/v8_crashpad_support_win.cc",
|
||||
"//chrome/child/v8_crashpad_support_win.h",
|
||||
@@ -137,15 +119,12 @@ static_library("chrome") {
|
||||
if (use_aura) {
|
||||
sources += [
|
||||
"//chrome/browser/platform_util_aura.cc",
|
||||
"//chrome/browser/ui/aura/native_window_tracker_aura.cc",
|
||||
"//chrome/browser/ui/aura/native_window_tracker_aura.h",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view_aura.cc",
|
||||
]
|
||||
}
|
||||
|
||||
public_deps = [
|
||||
"//chrome/browser:dev_ui_browser_resources",
|
||||
"//chrome/browser/ui/color:mixers",
|
||||
"//chrome/common",
|
||||
"//chrome/common:version_header",
|
||||
"//components/keyed_service/content",
|
||||
@@ -327,6 +306,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/pdf/pdf_frame_util.h",
|
||||
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.cc",
|
||||
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.h",
|
||||
"//chrome/renderer/pepper/chrome_pdf_print_client.cc",
|
||||
"//chrome/renderer/pepper/chrome_pdf_print_client.h",
|
||||
]
|
||||
deps += [
|
||||
"//components/pdf/browser",
|
||||
@@ -364,6 +345,8 @@ source_set("plugins") {
|
||||
sources += [
|
||||
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.cc",
|
||||
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.h",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc",
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.h",
|
||||
]
|
||||
@@ -371,20 +354,15 @@ source_set("plugins") {
|
||||
deps += [
|
||||
"//components/strings",
|
||||
"//media:media_buildflags",
|
||||
"//ppapi/buildflags",
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/proxy:ipc",
|
||||
"//ppapi/shared_impl",
|
||||
"//services/device/public/mojom",
|
||||
"//skia",
|
||||
"//storage/browser",
|
||||
]
|
||||
|
||||
if (enable_plugins) {
|
||||
deps += [
|
||||
"//ppapi/buildflags",
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/proxy:ipc",
|
||||
"//ppapi/shared_impl",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# This source set is just so we don't have to depend on all of //chrome/browser
|
||||
|
||||
@@ -66,9 +66,9 @@ async function createWindow (backgroundColor?: string) {
|
||||
mainWindow = new BrowserWindow(options);
|
||||
mainWindow.on('ready-to-show', () => mainWindow!.show());
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler(details => {
|
||||
shell.openExternal(decorateURL(details.url));
|
||||
return { action: 'deny' };
|
||||
mainWindow.webContents.on('new-window', (event, url) => {
|
||||
event.preventDefault();
|
||||
shell.openExternal(decorateURL(url));
|
||||
});
|
||||
|
||||
mainWindow.webContents.session.setPermissionRequestHandler((webContents, permission, done) => {
|
||||
|
||||
@@ -83,7 +83,7 @@ function loadApplicationPackage (packagePath: string) {
|
||||
});
|
||||
|
||||
try {
|
||||
// Override app's package.json data.
|
||||
// Override app name and version.
|
||||
packagePath = path.resolve(packagePath);
|
||||
const packageJsonPath = path.join(packagePath, 'package.json');
|
||||
let appPath;
|
||||
@@ -104,16 +104,6 @@ function loadApplicationPackage (packagePath: string) {
|
||||
} else if (packageJson.name) {
|
||||
app.name = packageJson.name;
|
||||
}
|
||||
if (packageJson.desktopName) {
|
||||
app.setDesktopName(packageJson.desktopName);
|
||||
} else {
|
||||
app.setDesktopName(`${app.name}.desktop`);
|
||||
}
|
||||
// Set v8 flags, deliberately lazy load so that apps that do not use this
|
||||
// feature do not pay the price
|
||||
if (packageJson.v8Flags) {
|
||||
require('v8').setFlagsFromString(packageJson.v8Flags);
|
||||
}
|
||||
appPath = packagePath;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,12 +64,15 @@ an issue:
|
||||
* [Automated Testing](tutorial/automated-testing.md)
|
||||
* [REPL](tutorial/repl.md)
|
||||
* [Distribution](tutorial/application-distribution.md)
|
||||
* [Supported Platforms](tutorial/support.md#supported-platforms)
|
||||
* [Code Signing](tutorial/code-signing.md)
|
||||
* [Mac App Store](tutorial/mac-app-store-submission-guide.md)
|
||||
* [Windows Store](tutorial/windows-store-guide.md)
|
||||
* [Snapcraft](tutorial/snapcraft.md)
|
||||
* [ASAR Archives](tutorial/asar-archives.md)
|
||||
* [Updates](tutorial/updates.md)
|
||||
* [Deploying an Update Server](tutorial/updates.md#deploying-an-update-server)
|
||||
* [Implementing Updates in Your App](tutorial/updates.md#implementing-updates-in-your-app)
|
||||
* [Applying Updates](tutorial/updates.md#applying-updates)
|
||||
* [Getting Support](tutorial/support.md)
|
||||
|
||||
## Detailed Tutorials
|
||||
@@ -83,6 +86,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)
|
||||
* [Testing Widevine CDM](tutorial/testing-widevine-cdm.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -484,6 +484,7 @@ Returns:
|
||||
* `argv` string[] - An array of the second instance's command line arguments
|
||||
* `workingDirectory` string - The second instance's working directory
|
||||
* `additionalData` unknown - A JSON object of additional data passed from the second instance
|
||||
* `ackCallback` unknown - A function that can be used to send data back to the second instance
|
||||
|
||||
This event will be emitted inside the primary instance of your application
|
||||
when a second instance has been executed and calls `app.requestSingleInstanceLock()`.
|
||||
@@ -495,12 +496,35 @@ non-minimized.
|
||||
|
||||
**Note:** If the second instance is started by a different user than the first, the `argv` array will not include the arguments.
|
||||
|
||||
**Note:** `ackCallback` allows the user to send data back to the
|
||||
second instance during the `app.requestSingleInstanceLock()` flow.
|
||||
This callback can be used for cases where the second instance
|
||||
needs to obtain additional information from the first instance
|
||||
before quitting.
|
||||
|
||||
Currently, the limit on the message size is kMaxMessageLength,
|
||||
or around 32kB. To be safe, keep the amount of data passed to 31kB at most.
|
||||
|
||||
In order to call the callback, `event.preventDefault()` must be called, first.
|
||||
If the callback is not called in either case, `null` will be sent back.
|
||||
If `event.preventDefault()` is not called, but `ackCallback` is called
|
||||
by the user in the event, then the behaviour is undefined.
|
||||
|
||||
This event is guaranteed to be emitted after the `ready` event of `app`
|
||||
gets emitted.
|
||||
|
||||
**Note:** Extra command line arguments might be added by Chromium,
|
||||
such as `--original-process-start-time`.
|
||||
|
||||
### Event: 'first-instance-ack'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `additionalData` unknown - A JSON object of additional data passed from the first instance, in response to the first instance's `second-instance` event.
|
||||
|
||||
This event will be emitted within the second instance during the call to `app.requestSingleInstanceLock()`, when the first instance calls the `ackCallback` provided by the `second-instance` event handler.
|
||||
|
||||
## Methods
|
||||
|
||||
The `app` object has the following methods:
|
||||
@@ -582,10 +606,6 @@ You should seek to use the `steal` option as sparingly as possible.
|
||||
|
||||
Hides all application windows without minimizing them.
|
||||
|
||||
### `app.isHidden()` _macOS_
|
||||
|
||||
Returns `boolean` - `true` if the application—including all of its windows—is hidden (e.g. with `Command-H`), `false` otherwise.
|
||||
|
||||
### `app.show()` _macOS_
|
||||
|
||||
Shows application windows after they were hidden. Does not automatically focus
|
||||
@@ -611,18 +631,9 @@ Returns `string` - The current application directory.
|
||||
* `%APPDATA%` on Windows
|
||||
* `$XDG_CONFIG_HOME` or `~/.config` on Linux
|
||||
* `~/Library/Application Support` on macOS
|
||||
* `userData` The directory for storing your app's configuration files, which
|
||||
by default is the `appData` directory appended with your app's name. By
|
||||
convention files storing user data should be written to this directory, and
|
||||
it is not recommended to write large files here because some environments
|
||||
may backup this directory to cloud storage.
|
||||
* `sessionData` The directory for storing data generated by `Session`, such
|
||||
as localStorage, cookies, disk cache, downloaded dictionaries, network
|
||||
state, devtools files. By default this points to `userData`. Chromium may
|
||||
write very large disk cache here, so if your app does not rely on browser
|
||||
storage like localStorage or cookies to save user data, it is recommended
|
||||
to set this directory to other locations to avoid polluting the `userData`
|
||||
directory.
|
||||
* `userData` The directory for storing your app's configuration files, which by
|
||||
default it is the `appData` directory appended with your app's name.
|
||||
* `cache`
|
||||
* `temp` Temporary directory.
|
||||
* `exe` The current executable file.
|
||||
* `module` The `libchromiumcontent` library.
|
||||
@@ -672,9 +683,9 @@ In that case, the directory should be created with `fs.mkdirSync` or similar.
|
||||
|
||||
You can only override paths of a `name` defined in `app.getPath`.
|
||||
|
||||
By default, web pages' cookies and caches will be stored under the `sessionData`
|
||||
By default, web pages' cookies and caches will be stored under the `userData`
|
||||
directory. If you want to change this location, you have to override the
|
||||
`sessionData` path before the `ready` event of the `app` module is emitted.
|
||||
`userData` path before the `ready` event of the `app` module is emitted.
|
||||
|
||||
### `app.getVersion()`
|
||||
|
||||
@@ -703,7 +714,7 @@ Overrides the current application's name.
|
||||
### `app.getLocale()`
|
||||
|
||||
Returns `string` - The current application locale, fetched using Chromium's `l10n_util` library.
|
||||
Possible return values are documented [here](https://source.chromium.org/chromium/chromium/src/+/main:ui/base/l10n/l10n_util.cc).
|
||||
Possible return values are documented [here](https://source.chromium.org/chromium/chromium/src/+/master:ui/base/l10n/l10n_util.cc).
|
||||
|
||||
To set the locale, you'll want to use a command line switch at app startup, which may be found [here](command-line-switches.md).
|
||||
|
||||
@@ -850,8 +861,6 @@ Returns `Object`:
|
||||
|
||||
* `categories` [JumpListCategory[]](structures/jump-list-category.md) | `null` - Array of `JumpListCategory` objects.
|
||||
|
||||
Returns `string`
|
||||
|
||||
Sets or removes a custom Jump List for the application, and returns one of the
|
||||
following strings:
|
||||
|
||||
@@ -974,6 +983,13 @@ starts:
|
||||
const { app } = require('electron')
|
||||
let myWindow = null
|
||||
|
||||
app.on('first-instance-ack', (event, additionalData) => {
|
||||
// Print out the ack received from the first instance.
|
||||
// Note this event handler must come before the requestSingleInstanceLock call.
|
||||
// Expected output: '{"myAckKey":"myAckValue"}'
|
||||
console.log(JSON.stringify(additionalData))
|
||||
})
|
||||
|
||||
const additionalData = { myKey: 'myValue' }
|
||||
const gotTheLock = app.requestSingleInstanceLock(additionalData)
|
||||
|
||||
@@ -981,14 +997,19 @@ if (!gotTheLock) {
|
||||
app.quit()
|
||||
} else {
|
||||
app.on('second-instance', (event, commandLine, workingDirectory, additionalData) => {
|
||||
// We must call preventDefault if we're sending back data.
|
||||
event.preventDefault()
|
||||
// Print out data received from the second instance.
|
||||
console.log(additionalData)
|
||||
// Expected output: '{"myKey":"myValue"}'
|
||||
console.log(JSON.stringify(additionalData))
|
||||
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
if (myWindow) {
|
||||
if (myWindow.isMinimized()) myWindow.restore()
|
||||
myWindow.focus()
|
||||
}
|
||||
const ackData = { myAckKey: 'myAckValue' }
|
||||
ackCallback(ackData)
|
||||
})
|
||||
|
||||
// Create myWindow, load the rest of the app, etc...
|
||||
@@ -1072,7 +1093,7 @@ Activation policy types:
|
||||
|
||||
Imports the certificate in pkcs12 format into the platform certificate store.
|
||||
`callback` is called with the `result` of import operation, a value of `0`
|
||||
indicates success while any other value indicates failure according to Chromium [net_error_list](https://source.chromium.org/chromium/chromium/src/+/main:net/base/net_error_list.h).
|
||||
indicates success while any other value indicates failure according to Chromium [net_error_list](https://source.chromium.org/chromium/chromium/src/+/master:net/base/net_error_list.h).
|
||||
|
||||
### `app.configureHostResolver(options)`
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@ relative to its owning window. It is meant to be an alternative to the
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
This module cannot be used until the `ready` event of the `app`
|
||||
module is emitted.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
This module cannot be used until the `ready` event of the `app`
|
||||
module is emitted.
|
||||
|
||||
```javascript
|
||||
// In the main process.
|
||||
const { BrowserWindow } = require('electron')
|
||||
@@ -67,7 +64,7 @@ win.loadURL('https://github.com')
|
||||
```
|
||||
|
||||
Note that even for apps that use `ready-to-show` event, it is still recommended
|
||||
to set `backgroundColor` to make the app feel more native.
|
||||
to set `backgroundColor` to make app feel more native.
|
||||
|
||||
Some examples of valid `backgroundColor` values include:
|
||||
|
||||
@@ -161,20 +158,20 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `useContentSize` boolean (optional) - The `width` and `height` would be used as web
|
||||
page's size, which means the actual window's size will include window
|
||||
frame's size and be slightly larger. Default is `false`.
|
||||
* `center` boolean (optional) - Show window in the center of the screen. Default is `false`.
|
||||
* `center` boolean (optional) - Show window in the center of the screen.
|
||||
* `minWidth` Integer (optional) - Window's minimum width. Default is `0`.
|
||||
* `minHeight` Integer (optional) - Window's minimum height. Default is `0`.
|
||||
* `maxWidth` Integer (optional) - Window's maximum width. Default is no limit.
|
||||
* `maxHeight` Integer (optional) - Window's maximum height. Default is no limit.
|
||||
* `resizable` boolean (optional) - Whether window is resizable. Default is `true`.
|
||||
* `movable` boolean (optional) _macOS_ _Windows_ - Whether window is
|
||||
movable. This is not implemented on Linux. Default is `true`.
|
||||
* `minimizable` boolean (optional) _macOS_ _Windows_ - Whether window is
|
||||
minimizable. This is not implemented on Linux. Default is `true`.
|
||||
* `maximizable` boolean (optional) _macOS_ _Windows_ - Whether window is
|
||||
maximizable. This is not implemented on Linux. Default is `true`.
|
||||
* `closable` boolean (optional) _macOS_ _Windows_ - Whether window is
|
||||
closable. This is not implemented on Linux. Default is `true`.
|
||||
* `movable` boolean (optional) - Whether window is movable. This is not implemented
|
||||
on Linux. Default is `true`.
|
||||
* `minimizable` boolean (optional) - Whether window is minimizable. This is not
|
||||
implemented on Linux. Default is `true`.
|
||||
* `maximizable` boolean (optional) - Whether window is maximizable. This is not
|
||||
implemented on Linux. Default is `true`.
|
||||
* `closable` boolean (optional) - Whether window is closable. This is not implemented
|
||||
on Linux. Default is `true`.
|
||||
* `focusable` boolean (optional) - Whether the window can be focused. Default is
|
||||
`true`. On Windows setting `focusable: false` also implies setting
|
||||
`skipTaskbar: true`. On Linux setting `focusable: false` makes the window
|
||||
@@ -188,10 +185,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `fullscreenable` boolean (optional) - Whether the window can be put into fullscreen
|
||||
mode. On macOS, also whether the maximize/zoom button should toggle full
|
||||
screen mode or maximize window. Default is `true`.
|
||||
* `simpleFullscreen` boolean (optional) _macOS_ - Use pre-Lion fullscreen on
|
||||
macOS. Default is `false`.
|
||||
* `skipTaskbar` boolean (optional) _macOS_ _Windows_ - Whether to show the window in taskbar.
|
||||
Default is `false`.
|
||||
* `simpleFullscreen` boolean (optional) - Use pre-Lion fullscreen on macOS. Default is `false`.
|
||||
* `skipTaskbar` boolean (optional) - Whether to show the window in taskbar. Default is
|
||||
`false`.
|
||||
* `kiosk` boolean (optional) - Whether the window is in kiosk mode. Default is `false`.
|
||||
* `title` string (optional) - Default window title. Default is `"Electron"`. If the HTML tag `<title>` is defined in the HTML file loaded by `loadURL()`, this property will be ignored.
|
||||
* `icon` ([NativeImage](native-image.md) | string) (optional) - The window icon. On Windows it is
|
||||
@@ -205,30 +201,27 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `parent` BrowserWindow (optional) - Specify parent window. Default is `null`.
|
||||
* `modal` boolean (optional) - Whether this is a modal window. This only works when the
|
||||
window is a child window. Default is `false`.
|
||||
* `acceptFirstMouse` boolean (optional) _macOS_ - Whether clicking an
|
||||
inactive window will also click through to the web contents. Default is
|
||||
`false` on macOS. This option is not configurable on other platforms.
|
||||
* `acceptFirstMouse` boolean (optional) - Whether clicking an inactive window will also
|
||||
click through to the web contents. Default is `false` on macOS. This option is not
|
||||
configurable on other platforms.
|
||||
* `disableAutoHideCursor` boolean (optional) - Whether to hide cursor when typing.
|
||||
Default is `false`.
|
||||
* `autoHideMenuBar` boolean (optional) - Auto hide the menu bar unless the `Alt`
|
||||
key is pressed. Default is `false`.
|
||||
* `enableLargerThanScreen` boolean (optional) _macOS_ - Enable the window to
|
||||
be resized larger than screen. Only relevant for macOS, as other OSes
|
||||
allow larger-than-screen windows by default. Default is `false`.
|
||||
* `enableLargerThanScreen` boolean (optional) - Enable the window to be resized larger
|
||||
than screen. Only relevant for macOS, as other OSes allow
|
||||
larger-than-screen windows by default. Default is `false`.
|
||||
* `backgroundColor` string (optional) - The window's background color in Hex, RGB, RGBA, HSL, HSLA or named CSS color format. Alpha in #AARRGGBB format is supported if `transparent` is set to `true`. Default is `#FFF` (white). See [win.setBackgroundColor](browser-window.md#winsetbackgroundcolorbackgroundcolor) for more information.
|
||||
* `hasShadow` boolean (optional) - Whether window should have a shadow. Default is `true`.
|
||||
* `opacity` number (optional) _macOS_ _Windows_ - 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.
|
||||
* `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`.
|
||||
* `transparent` boolean (optional) - Makes the window [transparent](../tutorial/window-customization.md#create-transparent-windows).
|
||||
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) _macOS_ - Specify how the material
|
||||
appearance should reflect window activity state on macOS. Must be used
|
||||
with the `vibrancy` property. Possible values are:
|
||||
* `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.
|
||||
@@ -236,42 +229,36 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
Default is `default`. Possible values are:
|
||||
* `default` - Results in the standard title bar for macOS or Windows respectively.
|
||||
* `hidden` - Results in a hidden title bar and a full size content window. On macOS, the window still has the standard window controls (“traffic lights”) in the top left. On Windows, when combined with `titleBarOverlay: true` it will activate the Window Controls Overlay (see `titleBarOverlay` for more information), otherwise no window controls will be shown.
|
||||
* `hiddenInset` _macOS_ - Only on macOS, results in a hidden title bar
|
||||
with an alternative look where the traffic light buttons are slightly
|
||||
more inset from the window edge.
|
||||
* `customButtonsOnHover` _macOS_ - Only on macOS, results in a hidden
|
||||
title bar and a full size content window, the traffic light buttons will
|
||||
display when being hovered over in the top left of the window.
|
||||
**Note:** This option is currently experimental.
|
||||
* `trafficLightPosition` [Point](structures/point.md) (optional) _macOS_ -
|
||||
Set a custom position for the traffic light buttons in frameless windows.
|
||||
* `roundedCorners` boolean (optional) _macOS_ - Whether frameless window
|
||||
should have rounded corners on macOS. Default is `true`. Setting this property
|
||||
to `false` will prevent the window from being fullscreenable.
|
||||
* `fullscreenWindowTitle` boolean (optional) _macOS_ _Deprecated_ - Shows
|
||||
the title in the title bar in full screen mode on macOS for `hiddenInset`
|
||||
titleBarStyle. Default is `false`.
|
||||
* `hiddenInset` - Only on macOS, results in a hidden title bar with an alternative look
|
||||
where the traffic light buttons are slightly more inset from the window edge.
|
||||
* `customButtonsOnHover` - Only on macOS, results in a hidden title bar and a full size
|
||||
content window, the traffic light buttons will display when being hovered
|
||||
over in the top left of the window. **Note:** This option is currently
|
||||
experimental.
|
||||
* `trafficLightPosition` [Point](structures/point.md) (optional) - Set a
|
||||
custom position for the traffic light buttons in frameless windows.
|
||||
* `roundedCorners` boolean (optional) - Whether frameless window should have
|
||||
rounded corners on macOS. Default is `true`.
|
||||
* `fullscreenWindowTitle` boolean (optional) _Deprecated_ - Shows the title in
|
||||
the title bar in full screen mode on macOS for `hiddenInset` titleBarStyle.
|
||||
Default is `false`.
|
||||
* `thickFrame` boolean (optional) - Use `WS_THICKFRAME` style for frameless windows on
|
||||
Windows, which adds standard window frame. Setting it to `false` will remove
|
||||
window shadow and window animations. Default is `true`.
|
||||
* `vibrancy` string (optional) _macOS_ - Add a type of vibrancy effect to
|
||||
the window, only on macOS. Can be `appearance-based`, `light`, `dark`,
|
||||
`titlebar`, `selection`, `menu`, `popover`, `sidebar`, `medium-light`,
|
||||
`ultra-dark`, `header`, `sheet`, `window`, `hud`, `fullscreen-ui`,
|
||||
`tooltip`, `content`, `under-window`, or `under-page`. Please note that
|
||||
`appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` are
|
||||
deprecated and have been removed in macOS Catalina (10.15).
|
||||
* `zoomToPageWidth` boolean (optional) _macOS_ - Controls the behavior on
|
||||
macOS when option-clicking the green stoplight button on the toolbar or by
|
||||
clicking the Window > Zoom menu item. If `true`, the window will grow to
|
||||
the preferred width of the web page when zoomed, `false` will cause it to
|
||||
zoom to the width of the screen. This will also affect the behavior when
|
||||
calling `maximize()` directly. Default is `false`.
|
||||
* `tabbingIdentifier` string (optional) _macOS_ - Tab group name, allows
|
||||
opening the window as a native tab on macOS 10.12+. Windows with the same
|
||||
tabbing identifier will be grouped together. This also adds a native new
|
||||
tab button to your window's tab bar and allows your `app` and window to
|
||||
receive the `new-window-for-tab` event.
|
||||
* `vibrancy` string (optional) - Add a type of vibrancy effect to the window, only on
|
||||
macOS. Can be `appearance-based`, `light`, `dark`, `titlebar`, `selection`,
|
||||
`menu`, `popover`, `sidebar`, `medium-light`, `ultra-dark`, `header`, `sheet`, `window`, `hud`, `fullscreen-ui`, `tooltip`, `content`, `under-window`, or `under-page`. Please note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` are deprecated and have been removed in macOS Catalina (10.15).
|
||||
* `zoomToPageWidth` boolean (optional) - Controls the behavior on macOS when
|
||||
option-clicking the green stoplight button on the toolbar or by clicking the
|
||||
Window > Zoom menu item. If `true`, the window will grow to the preferred
|
||||
width of the web page when zoomed, `false` will cause it to zoom to the
|
||||
width of the screen. This will also affect the behavior when calling
|
||||
`maximize()` directly. Default is `false`.
|
||||
* `tabbingIdentifier` string (optional) - Tab group name, allows opening the
|
||||
window as a native tab on macOS 10.12+. Windows with the same tabbing
|
||||
identifier will be grouped together. This also adds a native new tab button
|
||||
to your window's tab bar and allows your `app` and window to receive the
|
||||
`new-window-for-tab` event.
|
||||
* `webPreferences` Object (optional) - Settings of web page's features.
|
||||
* `devTools` boolean (optional) - Whether to enable DevTools. If it is set to `false`, can not use `BrowserWindow.webContents.openDevTools()` to open DevTools. Default is `true`.
|
||||
* `nodeIntegration` boolean (optional) - Whether node integration is enabled.
|
||||
@@ -323,8 +310,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `plugins` boolean (optional) - Whether plugins should be enabled. Default is `false`.
|
||||
* `experimentalFeatures` boolean (optional) - Enables Chromium's experimental features.
|
||||
Default is `false`.
|
||||
* `scrollBounce` boolean (optional) _macOS_ - Enables scroll bounce
|
||||
(rubber banding) effect on macOS. Default is `false`.
|
||||
* `scrollBounce` boolean (optional) - Enables scroll bounce (rubber banding) effect on
|
||||
macOS. Default is `false`.
|
||||
* `enableBlinkFeatures` string (optional) - A list of feature strings separated by `,`, like
|
||||
`CSSVariables,KeyboardEventKey` to enable. The full list of supported feature
|
||||
strings can be found in the [RuntimeEnabledFeatures.json5][runtime-enabled-features]
|
||||
@@ -426,17 +413,13 @@ Possible values are:
|
||||
|
||||
* On Linux, possible types are `desktop`, `dock`, `toolbar`, `splash`,
|
||||
`notification`.
|
||||
* On macOS, possible types are `desktop`, `textured`, `panel`.
|
||||
* On macOS, possible types are `desktop`, `textured`.
|
||||
* The `textured` type adds metal gradient appearance
|
||||
(`NSWindowStyleMaskTexturedBackground`).
|
||||
(`NSTexturedBackgroundWindowMask`).
|
||||
* The `desktop` type places the window at the desktop background window level
|
||||
(`kCGDesktopWindowLevel - 1`). Note that desktop window will not receive
|
||||
focus, keyboard or mouse events, but you can use `globalShortcut` to receive
|
||||
input sparingly.
|
||||
* The `panel` type enables the window to float on top of full-screened apps
|
||||
by adding the `NSWindowStyleMaskNonactivatingPanel` style mask,normally
|
||||
reserved for NSPanel, at runtime. Also, the window will appear on all
|
||||
spaces (desktops).
|
||||
* On Windows, possible type is `toolbar`.
|
||||
|
||||
### Instance Events
|
||||
@@ -481,7 +464,7 @@ window.onbeforeunload = (e) => {
|
||||
// a non-void value will silently cancel the close.
|
||||
// It is recommended to use the dialog API to let the user confirm closing the
|
||||
// application.
|
||||
e.returnValue = false
|
||||
e.returnValue = false // equivalent to `return false` but not recommended
|
||||
}
|
||||
```
|
||||
|
||||
@@ -791,7 +774,7 @@ A `boolean` property that determines whether the window is in fullscreen mode.
|
||||
|
||||
A `boolean` property that determines whether the window is focusable.
|
||||
|
||||
#### `win.visibleOnAllWorkspaces` _macOS_ _Linux_
|
||||
#### `win.visibleOnAllWorkspaces`
|
||||
|
||||
A `boolean` property that determines whether the window is visible on all workspaces.
|
||||
|
||||
@@ -828,13 +811,13 @@ A `string` property that determines the title of the native window.
|
||||
|
||||
**Note:** The title of the web page can be different from the title of the native window.
|
||||
|
||||
#### `win.minimizable` _macOS_ _Windows_
|
||||
#### `win.minimizable`
|
||||
|
||||
A `boolean` property that determines whether the window can be manually minimized by user.
|
||||
|
||||
On Linux the setter is a no-op, although the getter returns `true`.
|
||||
|
||||
#### `win.maximizable` _macOS_ _Windows_
|
||||
#### `win.maximizable`
|
||||
|
||||
A `boolean` property that determines whether the window can be manually maximized by user.
|
||||
|
||||
@@ -849,13 +832,13 @@ maximizes the window.
|
||||
|
||||
A `boolean` property that determines whether the window can be manually resized by user.
|
||||
|
||||
#### `win.closable` _macOS_ _Windows_
|
||||
#### `win.closable`
|
||||
|
||||
A `boolean` property that determines whether the window can be manually closed by user.
|
||||
|
||||
On Linux the setter is a no-op, although the getter returns `true`.
|
||||
|
||||
#### `win.movable` _macOS_ _Windows_
|
||||
#### `win.movable`
|
||||
|
||||
A `boolean` property that determines Whether the window can be moved by user.
|
||||
|
||||
@@ -1324,7 +1307,7 @@ win.setSheetOffset(toolbarRect.height)
|
||||
|
||||
Starts or stops flashing the window to attract user's attention.
|
||||
|
||||
#### `win.setSkipTaskbar(skip)` _macOS_ _Windows_
|
||||
#### `win.setSkipTaskbar(skip)`
|
||||
|
||||
* `skip` boolean
|
||||
|
||||
@@ -1652,7 +1635,7 @@ Changes window icon.
|
||||
|
||||
Sets whether the window traffic light buttons should be visible.
|
||||
|
||||
#### `win.setAutoHideMenuBar(hide)` _Windows_ _Linux_
|
||||
#### `win.setAutoHideMenuBar(hide)`
|
||||
|
||||
* `hide` boolean
|
||||
|
||||
@@ -1661,7 +1644,7 @@ menu bar will only show when users press the single `Alt` key.
|
||||
|
||||
If the menu bar is already visible, calling `setAutoHideMenuBar(true)` won't hide it immediately.
|
||||
|
||||
#### `win.isMenuBarAutoHide()` _Windows_ _Linux_
|
||||
#### `win.isMenuBarAutoHide()`
|
||||
|
||||
Returns `boolean` - Whether menu bar automatically hides itself.
|
||||
|
||||
@@ -1671,11 +1654,11 @@ Returns `boolean` - Whether menu bar automatically hides itself.
|
||||
|
||||
Sets whether the menu bar should be visible. If the menu bar is auto-hide, users can still bring up the menu bar by pressing the single `Alt` key.
|
||||
|
||||
#### `win.isMenuBarVisible()` _Windows_ _Linux_
|
||||
#### `win.isMenuBarVisible()`
|
||||
|
||||
Returns `boolean` - Whether the menu bar is visible.
|
||||
|
||||
#### `win.setVisibleOnAllWorkspaces(visible[, options])` _macOS_ _Linux_
|
||||
#### `win.setVisibleOnAllWorkspaces(visible[, options])`
|
||||
|
||||
* `visible` boolean
|
||||
* `options` Object (optional)
|
||||
@@ -1693,7 +1676,7 @@ Sets whether the window should be visible on all workspaces.
|
||||
|
||||
**Note:** This API does nothing on Windows.
|
||||
|
||||
#### `win.isVisibleOnAllWorkspaces()` _macOS_ _Linux_
|
||||
#### `win.isVisibleOnAllWorkspaces()`
|
||||
|
||||
Returns `boolean` - Whether the window is visible on all workspaces.
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ the first write will throw an error. If the passed value is not a `string`, its
|
||||
|
||||
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/+/main:services/network/public/cpp/header_util.cc;drc=1562cab3f1eda927938f8f4a5a91991fefde66d3;bpv=1;bpt=1;l=22).
|
||||
[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`
|
||||
|
||||
@@ -274,8 +274,8 @@ By default inspector websocket url is available in stderr and under /json/list e
|
||||
[ready]: app.md#event-ready
|
||||
[play-silent-audio]: https://github.com/atom/atom/pull/9485/files
|
||||
[debugging-main-process]: ../tutorial/debugging-main-process.md
|
||||
[logging]: https://source.chromium.org/chromium/chromium/src/+/main:base/logging.h
|
||||
[logging]: https://source.chromium.org/chromium/chromium/src/+/master:base/logging.h
|
||||
[node-cli]: https://nodejs.org/api/cli.html
|
||||
[play-silent-audio]: https://github.com/atom/atom/pull/9485/files
|
||||
[ready]: app.md#event-ready
|
||||
[severities]: https://source.chromium.org/chromium/chromium/src/+/main:base/logging.h?q=logging::LogSeverity&ss=chromium
|
||||
[severities]: https://source.chromium.org/chromium/chromium/src/+/master:base/logging.h?q=logging::LogSeverity&ss=chromium
|
||||
|
||||
@@ -36,7 +36,7 @@ Returns `Promise<string[]>` - resolves with an array of category groups once all
|
||||
|
||||
Get a set of category groups. The category groups can change as new code paths
|
||||
are reached. See also the [list of built-in tracing
|
||||
categories](https://chromium.googlesource.com/chromium/src/+/main/base/trace_event/builtin_categories.h).
|
||||
categories](https://chromium.googlesource.com/chromium/src/+/master/base/trace_event/builtin_categories.h).
|
||||
|
||||
> **NOTE:** Electron adds a non-default tracing category called `"electron"`.
|
||||
> This category can be used to capture Electron-specific tracing events.
|
||||
|
||||
@@ -35,7 +35,7 @@ page you load in your renderer executes code in this world.
|
||||
|
||||
When `contextIsolation` is enabled in your `webPreferences` (this is the default behavior since Electron 12.0.0), your `preload` scripts run in an
|
||||
"Isolated World". You can read more about context isolation and what it affects in the
|
||||
[security](../tutorial/security.md#3-enable-context-isolation) docs.
|
||||
[security](../tutorial/security.md#3-enable-context-isolation-for-remote-content) docs.
|
||||
|
||||
## Methods
|
||||
|
||||
|
||||
@@ -99,7 +99,6 @@ Only `chrome.storage.local` is supported; `chrome.storage.sync` and
|
||||
The following methods of `chrome.tabs` are supported:
|
||||
|
||||
- `chrome.tabs.sendMessage`
|
||||
- `chrome.tabs.reload`
|
||||
- `chrome.tabs.executeScript`
|
||||
- `chrome.tabs.update` (partial support)
|
||||
- supported properties: `url`, `muted`.
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
---
|
||||
title: "ipcMain"
|
||||
description: "Communicate asynchronously from the main process to renderer processes."
|
||||
slug: ipc-main
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
# ipcMain
|
||||
|
||||
> Communicate asynchronously from the main process to renderer processes.
|
||||
@@ -16,9 +9,7 @@ process, it handles asynchronous and synchronous messages sent from a renderer
|
||||
process (web page). Messages sent from a renderer will be emitted to this
|
||||
module.
|
||||
|
||||
For usage examples, check out the [IPC tutorial].
|
||||
|
||||
## Sending messages
|
||||
## Sending Messages
|
||||
|
||||
It is also possible to send messages from the main process to the renderer
|
||||
process, see [webContents.send][web-contents-send] for more information.
|
||||
@@ -30,6 +21,36 @@ process, see [webContents.send][web-contents-send] for more information.
|
||||
coming from frames that aren't the main frame (e.g. iframes) whereas
|
||||
`event.sender.send(...)` will always send to the main frame.
|
||||
|
||||
An example of sending and handling messages between the render and main
|
||||
processes:
|
||||
|
||||
```javascript
|
||||
// In main process.
|
||||
const { ipcMain } = require('electron')
|
||||
ipcMain.on('asynchronous-message', (event, arg) => {
|
||||
console.log(arg) // prints "ping"
|
||||
event.reply('asynchronous-reply', 'pong')
|
||||
})
|
||||
|
||||
ipcMain.on('synchronous-message', (event, arg) => {
|
||||
console.log(arg) // prints "ping"
|
||||
event.returnValue = 'pong'
|
||||
})
|
||||
```
|
||||
|
||||
```javascript
|
||||
// In renderer process (web page).
|
||||
// NB. Electron APIs are only accessible from preload, unless contextIsolation is disabled.
|
||||
// See https://www.electronjs.org/docs/tutorial/process-model#preload-scripts for more details.
|
||||
const { ipcRenderer } = require('electron')
|
||||
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"
|
||||
|
||||
ipcRenderer.on('asynchronous-reply', (event, arg) => {
|
||||
console.log(arg) // prints "pong"
|
||||
})
|
||||
ipcRenderer.send('asynchronous-message', 'ping')
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
The `ipcMain` module has the following method to listen for events:
|
||||
@@ -38,7 +59,7 @@ The `ipcMain` module has the following method to listen for events:
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` [IpcMainEvent][ipc-main-event]
|
||||
* `event` IpcMainEvent
|
||||
* `...args` any[]
|
||||
|
||||
Listens to `channel`, when a new message arrives `listener` would be called with
|
||||
@@ -48,7 +69,7 @@ Listens to `channel`, when a new message arrives `listener` would be called with
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` [IpcMainEvent][ipc-main-event]
|
||||
* `event` IpcMainEvent
|
||||
* `...args` any[]
|
||||
|
||||
Adds a one time `listener` function for the event. This `listener` is invoked
|
||||
@@ -72,8 +93,8 @@ Removes listeners of the specified `channel`.
|
||||
### `ipcMain.handle(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `event` IpcMainInvokeEvent
|
||||
* `...args` any[]
|
||||
|
||||
Adds a handler for an `invoke`able IPC. This handler will be called whenever a
|
||||
@@ -83,14 +104,14 @@ If `listener` returns a Promise, the eventual result of the promise will be
|
||||
returned as a reply to the remote caller. Otherwise, the return value of the
|
||||
listener will be used as the value of the reply.
|
||||
|
||||
```js title='Main Process'
|
||||
```js
|
||||
// Main process
|
||||
ipcMain.handle('my-invokable-ipc', async (event, ...args) => {
|
||||
const result = await somePromise(...args)
|
||||
return result
|
||||
})
|
||||
```
|
||||
|
||||
```js title='Renderer Process'
|
||||
// Renderer process
|
||||
async () => {
|
||||
const result = await ipcRenderer.invoke('my-invokable-ipc', arg1, arg2)
|
||||
// ...
|
||||
@@ -109,7 +130,7 @@ provided to the renderer process. Please refer to
|
||||
### `ipcMain.handleOnce(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `listener` Function<Promise\<void> | any>
|
||||
* `event` IpcMainInvokeEvent
|
||||
* `...args` any[]
|
||||
|
||||
@@ -125,16 +146,13 @@ Removes any handler for `channel`, if present.
|
||||
## IpcMainEvent object
|
||||
|
||||
The documentation for the `event` object passed to the `callback` can be found
|
||||
in the [`ipc-main-event`][ipc-main-event] structure docs.
|
||||
in the [`ipc-main-event`](structures/ipc-main-event.md) structure docs.
|
||||
|
||||
## IpcMainInvokeEvent object
|
||||
|
||||
The documentation for the `event` object passed to `handle` callbacks can be
|
||||
found in the [`ipc-main-invoke-event`][ipc-main-invoke-event]
|
||||
found in the [`ipc-main-invoke-event`](structures/ipc-main-invoke-event.md)
|
||||
structure docs.
|
||||
|
||||
[IPC tutorial]: ../tutorial/ipc.md
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[web-contents-send]: ../api/web-contents.md#contentssendchannel-args
|
||||
[ipc-main-event]:../api/structures/ipc-main-event.md
|
||||
[ipc-main-invoke-event]:../api/structures/ipc-main-invoke-event.md
|
||||
[web-contents-send]: web-contents.md#contentssendchannel-args
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
---
|
||||
title: "ipcRenderer"
|
||||
description: "Communicate asynchronously from a renderer process to the main process."
|
||||
slug: ipc-renderer
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
# ipcRenderer
|
||||
|
||||
> Communicate asynchronously from a renderer process to the main process.
|
||||
@@ -16,7 +9,7 @@ methods so you can send synchronous and asynchronous messages from the render
|
||||
process (web page) to the main process. You can also receive replies from the
|
||||
main process.
|
||||
|
||||
See [IPC tutorial](../tutorial/ipc.md) for code examples.
|
||||
See [ipcMain](ipc-main.md) for code examples.
|
||||
|
||||
## Methods
|
||||
|
||||
@@ -77,7 +70,7 @@ throw an exception.
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
The main process handles it by listening for `channel` with the
|
||||
[`ipcMain`](./ipc-main.md) module.
|
||||
[`ipcMain`](ipc-main.md) module.
|
||||
|
||||
If you need to transfer a [`MessagePort`][] to the main process, use [`ipcRenderer.postMessage`](#ipcrendererpostmessagechannel-message-transfer).
|
||||
|
||||
@@ -96,8 +89,16 @@ Algorithm][SCA], just like [`window.postMessage`][], so prototype chains will no
|
||||
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
> **NOTE:** Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
>
|
||||
> Since the main process does not have support for DOM objects such as
|
||||
> `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over
|
||||
> Electron's IPC to the main process, as the main process would have no way to decode
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
The main process should listen for `channel` with
|
||||
[`ipcMain.handle()`](./ipc-main.md#ipcmainhandlechannel-listener).
|
||||
[`ipcMain.handle()`](ipc-main.md#ipcmainhandlechannel-listener).
|
||||
|
||||
For example:
|
||||
|
||||
@@ -118,31 +119,16 @@ If you need to transfer a [`MessagePort`][] to the main process, use [`ipcRender
|
||||
|
||||
If you do not need a response to the message, consider using [`ipcRenderer.send`](#ipcrenderersendchannel-args).
|
||||
|
||||
> **Note**
|
||||
> Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
>
|
||||
> Since the main process does not have support for DOM objects such as
|
||||
> `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over
|
||||
> Electron's IPC to the main process, as the main process would have no way to decode
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
> **Note**
|
||||
> If the handler in the main process throws an error,
|
||||
> the promise returned by `invoke` will reject.
|
||||
> However, the `Error` object in the renderer process
|
||||
> will not be the same as the one thrown in the main process.
|
||||
|
||||
### `ipcRenderer.sendSync(channel, ...args)`
|
||||
|
||||
* `channel` string
|
||||
* `...args` any[]
|
||||
|
||||
Returns `any` - The value sent back by the [`ipcMain`](./ipc-main.md) handler.
|
||||
Returns `any` - The value sent back by the [`ipcMain`](ipc-main.md) handler.
|
||||
|
||||
Send a message to the main process via `channel` and expect a result
|
||||
synchronously. Arguments will be serialized with the [Structured Clone
|
||||
Algorithm][SCA], just like [`window.postMessage`], so prototype chains will not be
|
||||
Algorithm][SCA], just like [`window.postMessage`][], so prototype chains will not be
|
||||
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
@@ -154,13 +140,13 @@ throw an exception.
|
||||
> Electron's IPC to the main process, as the main process would have no way to decode
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
The main process handles it by listening for `channel` with [`ipcMain`](./ipc-main.md) module,
|
||||
The main process handles it by listening for `channel` with [`ipcMain`](ipc-main.md) module,
|
||||
and replies by setting `event.returnValue`.
|
||||
|
||||
> :warning: **WARNING**: Sending a synchronous message will block the whole
|
||||
> renderer process until the reply is received, so use this method only as a
|
||||
> last resort. It's much better to use the asynchronous version,
|
||||
> [`invoke()`](./ipc-renderer.md#ipcrendererinvokechannel-args).
|
||||
> [`invoke()`](ipc-renderer.md#ipcrendererinvokechannel-args).
|
||||
|
||||
### `ipcRenderer.postMessage(channel, message, [transfer])`
|
||||
|
||||
@@ -172,7 +158,7 @@ Send a message to the main process, optionally transferring ownership of zero
|
||||
or more [`MessagePort`][] objects.
|
||||
|
||||
The transferred `MessagePort` objects will be available in the main process as
|
||||
[`MessagePortMain`](./message-port-main.md) objects by accessing the `ports`
|
||||
[`MessagePortMain`](message-port-main.md) objects by accessing the `ports`
|
||||
property of the emitted event.
|
||||
|
||||
For example:
|
||||
@@ -211,7 +197,7 @@ the host page instead of the main process.
|
||||
## Event object
|
||||
|
||||
The documentation for the `event` object passed to the `callback` can be found
|
||||
in the [`ipc-renderer-event`](./structures/ipc-renderer-event.md) structure docs.
|
||||
in the [`ipc-renderer-event`](structures/ipc-renderer-event.md) structure docs.
|
||||
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[SCA]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
||||
|
||||
@@ -10,12 +10,11 @@ An example of implementing a protocol that has the same effect as the
|
||||
```javascript
|
||||
const { app, protocol } = require('electron')
|
||||
const path = require('path')
|
||||
const url = require('url')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
protocol.registerFileProtocol('atom', (request, callback) => {
|
||||
const filePath = url.fileURLToPath('file://' + request.url.slice('atom://'.length))
|
||||
callback(filePath)
|
||||
const url = request.url.substr(7)
|
||||
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
||||
})
|
||||
})
|
||||
```
|
||||
@@ -176,7 +175,7 @@ property.
|
||||
* `handler` Function
|
||||
* `request` [ProtocolRequest](structures/protocol-request.md)
|
||||
* `callback` Function
|
||||
* `response` [ProtocolResponse](structures/protocol-response.md)
|
||||
* `response` ProtocolResponse
|
||||
|
||||
Returns `boolean` - Whether the protocol was successfully registered
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ The `safeStorage` module has the following methods:
|
||||
|
||||
Returns `boolean` - Whether encryption is available.
|
||||
|
||||
On Linux, returns true if the app has emitted the `ready` event and the secret key is available.
|
||||
On MacOS, returns true if Keychain is available.
|
||||
On Linux, returns true if the secret key is
|
||||
available. On MacOS, returns true if Keychain is available.
|
||||
On Windows, returns true once the app has emitted the `ready` event.
|
||||
|
||||
### `safeStorage.encryptString(plainText)`
|
||||
|
||||
@@ -253,11 +253,9 @@ Returns:
|
||||
* `device` [HIDDevice[]](structures/hid-device.md)
|
||||
* `frame` [WebFrameMain](web-frame-main.md)
|
||||
|
||||
Emitted after `navigator.hid.requestDevice` has been called and
|
||||
`select-hid-device` has fired if a new device becomes available before
|
||||
the callback from `select-hid-device` is called. This event is intended for
|
||||
use when using a UI to ask users to pick a device so that the UI can be updated
|
||||
with the newly added device.
|
||||
Emitted when a new HID device becomes available. For example, when a new USB device is plugged in.
|
||||
|
||||
This event will only be emitted after `navigator.hid.requestDevice` has been called and `select-hid-device` has fired.
|
||||
|
||||
#### Event: 'hid-device-removed'
|
||||
|
||||
@@ -268,24 +266,9 @@ Returns:
|
||||
* `device` [HIDDevice[]](structures/hid-device.md)
|
||||
* `frame` [WebFrameMain](web-frame-main.md)
|
||||
|
||||
Emitted after `navigator.hid.requestDevice` has been called and
|
||||
`select-hid-device` has fired if a device has been removed before the callback
|
||||
from `select-hid-device` is called. This event is intended for use when using
|
||||
a UI to ask users to pick a device so that the UI can be updated to remove the
|
||||
specified device.
|
||||
Emitted when a HID device has been removed. For example, this event will fire when a USB device is unplugged.
|
||||
|
||||
#### Event: 'hid-device-revoked'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `details` Object
|
||||
* `device` [HIDDevice[]](structures/hid-device.md)
|
||||
* `origin` string (optional) - The origin that the device has been revoked from.
|
||||
|
||||
Emitted after `HIDDevice.forget()` has been called. This event can be used
|
||||
to help maintain persistent storage of permissions when
|
||||
`setDevicePermissionHandler` is used.
|
||||
This event will only be emitted after `navigator.hid.requestDevice` has been called and `select-hid-device` has fired.
|
||||
|
||||
#### Event: 'select-serial-port'
|
||||
|
||||
@@ -365,11 +348,7 @@ Returns:
|
||||
* `port` [SerialPort](structures/serial-port.md)
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
|
||||
Emitted after `navigator.serial.requestPort` has been called and
|
||||
`select-serial-port` has fired if a new serial port becomes available before
|
||||
the callback from `select-serial-port` is called. This event is intended for
|
||||
use when using a UI to ask users to pick a port so that the UI can be updated
|
||||
with the newly added port.
|
||||
Emitted after `navigator.serial.requestPort` has been called and `select-serial-port` has fired if a new serial port becomes available. For example, this event will fire when a new USB device is plugged in.
|
||||
|
||||
#### Event: 'serial-port-removed'
|
||||
|
||||
@@ -379,11 +358,7 @@ Returns:
|
||||
* `port` [SerialPort](structures/serial-port.md)
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
|
||||
Emitted after `navigator.serial.requestPort` has been called and
|
||||
`select-serial-port` has fired if a serial port has been removed before the
|
||||
callback from `select-serial-port` is called. This event is intended for use
|
||||
when using a UI to ask users to pick a port so that the UI can be updated
|
||||
to remove the specified port.
|
||||
Emitted after `navigator.serial.requestPort` has been called and `select-serial-port` has fired if a serial port has been removed. For example, this event will fire when a USB device is unplugged.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
@@ -592,7 +567,7 @@ the original network configuration.
|
||||
* `errorCode` Integer - Error code.
|
||||
* `callback` Function
|
||||
* `verificationResult` Integer - Value can be one of certificate error codes
|
||||
from [here](https://source.chromium.org/chromium/chromium/src/+/main:net/base/net_error_list.h).
|
||||
from [here](https://source.chromium.org/chromium/chromium/src/+/master:net/base/net_error_list.h).
|
||||
Apart from the certificate error codes, the following special codes can be used.
|
||||
* `0` - Indicates success and disables Certificate Transparency verification.
|
||||
* `-2` - Indicates failure.
|
||||
@@ -635,7 +610,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
|
||||
* `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. These requests always appear to originate from the main frame.
|
||||
* `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.
|
||||
* `unknown` - An unrecognized permission request
|
||||
@@ -705,6 +680,7 @@ session.fromPartition('some-partition').setPermissionCheckHandler((webContents,
|
||||
* `deviceType` string - The type of device that permission is being requested on, can be `hid` or `serial`.
|
||||
* `origin` string - The origin URL of the device permission check.
|
||||
* `device` [HIDDevice](structures/hid-device.md) | [SerialPort](structures/serial-port.md)- the device that permission is being requested for.
|
||||
* `frame` [WebFrameMain](web-frame-main.md) - WebFrameMain checking the device permission.
|
||||
|
||||
Sets the handler which can be used to respond to device permission checks for the `session`.
|
||||
Returning `true` will allow the device to be permitted and `false` will reject it.
|
||||
@@ -712,8 +688,8 @@ To clear the handler, call `setDevicePermissionHandler(null)`.
|
||||
This handler can be used to provide default permissioning to devices without first calling for permission
|
||||
to devices (eg via `navigator.hid.requestDevice`). If this handler is not defined, the default device
|
||||
permissions as granted through device selection (eg via `navigator.hid.requestDevice`) will be used.
|
||||
Additionally, the default behavior of Electron is to store granted device permision in memory.
|
||||
If longer term storage is needed, a developer can store granted device
|
||||
Additionally, the default behavior of Electron is to store granted device permision through the lifetime
|
||||
of the corresponding WebContents. If longer term storage is needed, a developer can store granted device
|
||||
permissions (eg when handling the `select-hid-device` event) and then read from that storage with `setDevicePermissionHandler`.
|
||||
|
||||
```javascript
|
||||
@@ -1049,7 +1025,7 @@ is emitted.
|
||||
|
||||
#### `ses.getStoragePath()`
|
||||
|
||||
Returns `string | null` - The absolute file system path where data for this
|
||||
A `string | null` indicating the absolute file system path where data for this
|
||||
session is persisted on disk. For in memory sessions this returns `null`.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
@@ -31,4 +31,4 @@
|
||||
* `uploadData` [ProtocolResponseUploadData](protocol-response-upload-data.md) (optional) - The data used as upload data. This is only
|
||||
used for URL responses when `method` is `"POST"`.
|
||||
|
||||
[net-error]: https://source.chromium.org/chromium/chromium/src/+/main:net/base/net_error_list.h
|
||||
[net-error]: https://source.chromium.org/chromium/chromium/src/+/master:net/base/net_error_list.h
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* `enable_argument_filter` boolean (optional) - if true, filter event data
|
||||
according to a specific list of events that have been manually vetted to not
|
||||
include any PII. See [the implementation in
|
||||
Chromium][trace_event_args_allowlist.cc] for specifics.
|
||||
Chromium][trace_event_args_whitelist.cc] for specifics.
|
||||
* `included_categories` string[] (optional) - a list of tracing categories to
|
||||
include. Can include glob-like patterns using `*` at the end of the category
|
||||
name. See [tracing categories][] for the list of categories.
|
||||
@@ -45,7 +45,7 @@ An example TraceConfig that roughly matches what Chrome DevTools records:
|
||||
}
|
||||
```
|
||||
|
||||
[tracing categories]: https://chromium.googlesource.com/chromium/src/+/main/base/trace_event/builtin_categories.h
|
||||
[memory-infra docs]: https://chromium.googlesource.com/chromium/src/+/main/docs/memory-infra/memory_infra_startup_tracing.md#the-advanced-way
|
||||
[trace_event_args_allowlist.cc]: https://chromium.googlesource.com/chromium/src/+/main/services/tracing/public/cpp/trace_event_args_allowlist.cc
|
||||
[tracing categories]: https://chromium.googlesource.com/chromium/src/+/master/base/trace_event/builtin_categories.h
|
||||
[memory-infra docs]: https://chromium.googlesource.com/chromium/src/+/master/docs/memory-infra/memory_infra_startup_tracing.md#the-advanced-way
|
||||
[trace_event_args_whitelist.cc]: https://chromium.googlesource.com/chromium/src/+/master/services/tracing/public/cpp/trace_event_args_whitelist.cc
|
||||
[histogram]: https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md
|
||||
|
||||
@@ -84,7 +84,7 @@ that contains the user information dictionary sent along with the notification.
|
||||
|
||||
### `systemPreferences.subscribeNotification(event, callback)` _macOS_
|
||||
|
||||
* `event` string | null
|
||||
* `event` string
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record<string, unknown>
|
||||
@@ -109,11 +109,9 @@ example values of `event` are:
|
||||
* `AppleColorPreferencesChangedNotification`
|
||||
* `AppleShowScrollBarsSettingChanged`
|
||||
|
||||
If `event` is null, the `NSDistributedNotificationCenter` doesn’t use it as criteria for delivery to the observer. See [docs](https://developer.apple.com/documentation/foundation/nsnotificationcenter/1411723-addobserverforname?language=objc) for more information.
|
||||
|
||||
### `systemPreferences.subscribeLocalNotification(event, callback)` _macOS_
|
||||
|
||||
* `event` string | null
|
||||
* `event` string
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record<string, unknown>
|
||||
@@ -124,11 +122,9 @@ Returns `number` - The ID of this subscription
|
||||
Same as `subscribeNotification`, but uses `NSNotificationCenter` for local defaults.
|
||||
This is necessary for events such as `NSUserDefaultsDidChangeNotification`.
|
||||
|
||||
If `event` is null, the `NSNotificationCenter` doesn’t use it as criteria for delivery to the observer. See [docs](https://developer.apple.com/documentation/foundation/nsnotificationcenter/1411723-addobserverforname?language=objc) for more information.
|
||||
|
||||
### `systemPreferences.subscribeWorkspaceNotification(event, callback)` _macOS_
|
||||
|
||||
* `event` string | null
|
||||
* `event` string
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record<string, unknown>
|
||||
@@ -139,8 +135,6 @@ Returns `number` - The ID of this subscription
|
||||
Same as `subscribeNotification`, but uses `NSWorkspace.sharedWorkspace.notificationCenter`.
|
||||
This is necessary for events such as `NSWorkspaceDidActivateApplicationNotification`.
|
||||
|
||||
If `event` is null, the `NSWorkspaceNotificationCenter` doesn’t use it as criteria for delivery to the observer. See [docs](https://developer.apple.com/documentation/foundation/nsnotificationcenter/1411723-addobserverforname?language=objc) for more information.
|
||||
|
||||
### `systemPreferences.unsubscribeNotification(id)` _macOS_
|
||||
|
||||
* `id` Integer
|
||||
@@ -183,11 +177,11 @@ Some popular `key` and `type`s are:
|
||||
* `NSPreferredWebServices`: `dictionary`
|
||||
* `NSUserDictionaryReplacementItems`: `array`
|
||||
|
||||
### `systemPreferences.setUserDefault<Type extends keyof UserDefaultTypes>(key, type, value)` _macOS_
|
||||
### `systemPreferences.setUserDefault(key, type, value)` _macOS_
|
||||
|
||||
* `key` string
|
||||
* `type` Type - Can be `string`, `boolean`, `integer`, `float`, `double`, `url`, `array` or `dictionary`.
|
||||
* `value` UserDefaultTypes[Type]
|
||||
* `type` string - Can be `string`, `boolean`, `integer`, `float`, `double`, `url`, `array` or `dictionary`.
|
||||
* `value` string
|
||||
|
||||
Set the value of `key` in `NSUserDefaults`.
|
||||
|
||||
|
||||
@@ -25,20 +25,15 @@ app.whenReady().then(() => {
|
||||
})
|
||||
```
|
||||
|
||||
__Platform Considerations__
|
||||
|
||||
If you want to keep exact same behaviors on all platforms, you should not
|
||||
rely on the `click` event; instead, always attach a context menu to the tray icon.
|
||||
|
||||
__Linux__
|
||||
__Platform limitations:__
|
||||
|
||||
* On Linux the app indicator will be used if it is supported, otherwise
|
||||
`GtkStatusIcon` will be used instead.
|
||||
* On Linux distributions that only have app indicator support, you have to
|
||||
install `libappindicator1` to make the tray icon work.
|
||||
* The app indicator will be used if it is supported, otherwise
|
||||
`GtkStatusIcon` will be used instead.
|
||||
* App indicator will only be shown when it has a context menu.
|
||||
* The `click` event is ignored when using the app indicator.
|
||||
* In order for changes made to individual `MenuItem`s to take effect,
|
||||
* When app indicator is used on Linux, the `click` event is ignored.
|
||||
* On Linux in order for changes made to individual `MenuItem`s to take effect,
|
||||
you have to call `setContextMenu` again. For example:
|
||||
|
||||
```javascript
|
||||
@@ -60,16 +55,10 @@ app.whenReady().then(() => {
|
||||
})
|
||||
```
|
||||
|
||||
__MacOS__
|
||||
* On Windows it is recommended to use `ICO` icons to get best visual effects.
|
||||
|
||||
* Icons passed to the Tray constructor should be [Template Images](native-image.md#template-image).
|
||||
* To make sure your icon isn't grainy on retina monitors, be sure your `@2x` image is 144dpi.
|
||||
* If you are bundling your application (e.g., with webpack for development), be sure that the file names are not being mangled or hashed. The filename needs to end in Template, and the `@2x` image needs to have the same filename as the standard image, or MacOS will not magically invert your image's colors or use the high density image.
|
||||
* 16x16 (72dpi) and 32x32@2x (144dpi) work well for most icons.
|
||||
|
||||
__Windows__
|
||||
|
||||
* It is recommended to use `ICO` icons to get best visual effects.
|
||||
If you want to keep exact same behaviors on all platforms, you should not
|
||||
rely on the `click` event and always attach a context menu to the tray icon.
|
||||
|
||||
### `new Tray(image, [guid])`
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ for all windows, webviews, opened devtools, and devtools extension background pa
|
||||
|
||||
### `webContents.getFocusedWebContents()`
|
||||
|
||||
Returns `WebContents` | null - The web contents that is focused in this application, otherwise
|
||||
Returns `WebContents` - The web contents that is focused in this application, otherwise
|
||||
returns `null`.
|
||||
|
||||
### `webContents.fromId(id)`
|
||||
@@ -92,7 +92,7 @@ Returns:
|
||||
* `frameRoutingId` Integer
|
||||
|
||||
This event is like `did-finish-load` but emitted when the load failed.
|
||||
The full list of error codes and their meaning is available [here](https://source.chromium.org/chromium/chromium/src/+/main:net/base/net_error_list.h).
|
||||
The full list of error codes and their meaning is available [here](https://source.chromium.org/chromium/chromium/src/+/master:net/base/net_error_list.h).
|
||||
|
||||
#### Event: 'did-fail-provisional-load'
|
||||
|
||||
@@ -820,6 +820,9 @@ 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`
|
||||
(not `preload`) in the `webPreferences` object emitted with this event.
|
||||
|
||||
#### Event: 'did-attach-webview'
|
||||
|
||||
Returns:
|
||||
@@ -1635,8 +1638,6 @@ Opens the devtools.
|
||||
When `contents` is a `<webview>` tag, the `mode` would be `detach` by default,
|
||||
explicitly passing an empty `mode` can force using last used dock state.
|
||||
|
||||
On Windows, if Windows Control Overlay is enabled, Devtools will be opened with `mode: 'detach'`.
|
||||
|
||||
#### `contents.closeDevTools()`
|
||||
|
||||
Closes the devtools.
|
||||
|
||||
@@ -16,7 +16,7 @@ win.loadURL('https://twitter.com')
|
||||
|
||||
win.webContents.on(
|
||||
'did-frame-navigate',
|
||||
(event, url, httpResponseCode, httpStatusText, isMainFrame, frameProcessId, frameRoutingId) => {
|
||||
(event, url, isMainFrame, frameProcessId, frameRoutingId) => {
|
||||
const frame = webFrameMain.fromId(frameProcessId, frameRoutingId)
|
||||
if (frame) {
|
||||
const code = 'document.body.innerHTML = document.body.innerHTML.replaceAll("heck", "h*ck")'
|
||||
@@ -144,16 +144,6 @@ ipcRenderer.on('port', (e, msg) => {
|
||||
|
||||
A `string` representing the current URL of the frame.
|
||||
|
||||
#### `frame.origin` _Readonly_
|
||||
|
||||
A `string` representing the current origin of the frame, serialized according
|
||||
to [RFC 6454](https://www.rfc-editor.org/rfc/rfc6454). This may be different
|
||||
from the URL. For instance, if the frame is a child window opened to
|
||||
`about:blank`, then `frame.origin` will return the parent frame's origin, while
|
||||
`frame.url` will return the empty string. Pages without a scheme/host/port
|
||||
triple origin will have the serialized origin of `"null"` (that is, the string
|
||||
containing the letters n, u, l, l).
|
||||
|
||||
#### `frame.top` _Readonly_
|
||||
|
||||
A `WebFrameMain | null` representing top frame in the frame hierarchy to which `frame`
|
||||
@@ -205,6 +195,3 @@ have the same `routingId`.
|
||||
A `string` representing the [visibility state](https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilityState) of the frame.
|
||||
|
||||
See also how the [Page Visibility API](browser-window.md#page-visibility) is affected by other Electron APIs.
|
||||
|
||||
[SCA]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
||||
[`postMessage`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
|
||||
|
||||
@@ -110,7 +110,7 @@ webFrame.setSpellCheckProvider('en-US', {
|
||||
})
|
||||
```
|
||||
|
||||
### `webFrame.insertCSS(css[, options])`
|
||||
#### `webFrame.insertCSS(css[, options])`
|
||||
|
||||
* `css` string
|
||||
* `options` Object (optional)
|
||||
|
||||
@@ -158,6 +158,9 @@ When the guest page doesn't have node integration this script will still have
|
||||
access to all Node APIs, but global objects injected by Node will be deleted
|
||||
after this script has finished executing.
|
||||
|
||||
**Note:** This option will appear as `preloadURL` (not `preload`) in
|
||||
the `webPreferences` specified to the `will-attach-webview` event.
|
||||
|
||||
### `httpreferrer`
|
||||
|
||||
```html
|
||||
@@ -556,7 +559,7 @@ Stops any `findInPage` request for the `webview` with the provided `action`.
|
||||
* `header` string (optional) - string to be printed as page header.
|
||||
* `footer` string (optional) - string to be printed as page footer.
|
||||
* `pageSize` string | Size (optional) - Specify page size of the printed document. Can be `A3`,
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` in microns.
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`.
|
||||
|
||||
Returns `Promise<void>`
|
||||
|
||||
|
||||
@@ -73,11 +73,6 @@ creating the window. Note that this is more powerful than passing options
|
||||
through the feature string, as the renderer has more limited privileges in
|
||||
deciding security preferences than the main process.
|
||||
|
||||
In addition to passing in `action` and `overrideBrowserWindowOptions`,
|
||||
`outlivesOpener` can be passed like: `{ action: 'allow', outlivesOpener: true,
|
||||
overrideBrowserWindowOptions: { ... } }`. If set to `true`, the newly created
|
||||
window will not close when the opener window closes. The default value is `false`.
|
||||
|
||||
### Native `Window` example
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -34,19 +34,9 @@ window manager. There is not a direct equivalent for Wayland, and the known
|
||||
workarounds have unacceptable tradeoffs (e.g. Window.is_skip_taskbar in GNOME
|
||||
requires unsafe mode), so Electron is unable to support this feature on Linux.
|
||||
|
||||
### API Changed: `session.setDevicePermissionHandler(handler)`
|
||||
|
||||
The handler invoked when `session.setDevicePermissionHandler(handler)` is used
|
||||
has a change to its arguments. This handler no longer is passed a frame
|
||||
`[WebFrameMain](api/web-frame-main.md)`, but instead is passed the `origin`, which
|
||||
is the origin that is checking for device permission.
|
||||
|
||||
## Planned Breaking API Changes (19.0)
|
||||
|
||||
### Removed: IA32 Linux binaries
|
||||
|
||||
This is a result of Chromium 102.0.4999.0 dropping support for IA32 Linux.
|
||||
This concludes the [removal of support for IA32 Linux](#removed-ia32-linux-support).
|
||||
*None (yet)*
|
||||
|
||||
## Planned Breaking API Changes (18.0)
|
||||
|
||||
@@ -382,7 +372,7 @@ value.
|
||||
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](tutorial/security.md#3-enable-context-isolation) for the security of your application.
|
||||
We [recommend having contextIsolation enabled](tutorial/security.md#3-enable-context-isolation-for-remote-content) for the security of your application.
|
||||
|
||||
Another implication is that `require()` cannot be used in the renderer process unless
|
||||
`nodeIntegration` is `true` and `contextIsolation` is `false`.
|
||||
@@ -1213,10 +1203,6 @@ not present, then the native module will fail to load on Windows, with an error
|
||||
message like `Cannot find module`. See the [native module
|
||||
guide](/docs/tutorial/using-native-node-modules.md) for more.
|
||||
|
||||
### Removed: IA32 Linux support
|
||||
|
||||
Electron 18 will no longer run on 32-bit Linux systems. See [discontinuing support for 32-bit Linux](https://www.electronjs.org/blog/linux-32bit-support) for more information.
|
||||
|
||||
## Breaking API Changes (3.0)
|
||||
|
||||
The following list includes the breaking API changes in Electron 3.0.
|
||||
|
||||
@@ -196,12 +196,12 @@ If you test other combinations and find them to work, please update this documen
|
||||
See the GN reference for allowable values of [`target_os`][target_os values]
|
||||
and [`target_cpu`][target_cpu values].
|
||||
|
||||
[target_os values]: https://gn.googlesource.com/gn/+/main/docs/reference.md#built_in-predefined-variables-target_os_the-desired-operating-system-for-the-build-possible-values
|
||||
[target_cpu values]: https://gn.googlesource.com/gn/+/main/docs/reference.md#built_in-predefined-variables-target_cpu_the-desired-cpu-architecture-for-the-build-possible-values
|
||||
[target_os values]: https://gn.googlesource.com/gn/+/master/docs/reference.md#built_in-predefined-variables-target_os_the-desired-operating-system-for-the-build-possible-values
|
||||
[target_cpu values]: https://gn.googlesource.com/gn/+/master/docs/reference.md#built_in-predefined-variables-target_cpu_the-desired-cpu-architecture-for-the-build-possible-values
|
||||
|
||||
#### Windows on Arm (experimental)
|
||||
|
||||
To cross-compile for Windows on Arm, [follow Chromium's guide](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/windows_build_instructions.md#Visual-Studio) to get the necessary dependencies, SDK and libraries, then build with `ELECTRON_BUILDING_WOA=1` in your environment before running `gclient sync`.
|
||||
To cross-compile for Windows on Arm, [follow Chromium's guide](https://chromium.googlesource.com/chromium/src/+/refs/heads/master/docs/windows_build_instructions.md#Visual-Studio) to get the necessary dependencies, SDK and libraries, then build with `ELECTRON_BUILDING_WOA=1` in your environment before running `gclient sync`.
|
||||
|
||||
```bat
|
||||
set ELECTRON_BUILDING_WOA=1
|
||||
|
||||
@@ -82,7 +82,7 @@ $ sudo apt-get install libc6-dev-arm64-cross linux-libc-dev-arm64-cross \
|
||||
g++-aarch64-linux-gnu
|
||||
```
|
||||
|
||||
And to cross-compile for `arm` or targets, you should pass the
|
||||
And to cross-compile for `arm` or `ia32` targets, you should pass the
|
||||
`target_cpu` parameter to `gn gen`:
|
||||
|
||||
```sh
|
||||
|
||||
@@ -9,12 +9,14 @@ Follow the guidelines below for building **Electron itself** on Windows, for the
|
||||
* Windows 10 / Server 2012 R2 or higher
|
||||
* Visual Studio 2017 15.7.2 or higher - [download VS 2019 Community Edition for
|
||||
free](https://www.visualstudio.com/vs/)
|
||||
* See [the Chromium build documentation](https://chromium.googlesource.com/chromium/src/+/main/docs/windows_build_instructions.md#visual-studio) for more details on which Visual Studio
|
||||
* See [the Chromium build documentation](https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md#visual-studio) for more details on which Visual Studio
|
||||
components are required.
|
||||
* If your Visual Studio is installed in a directory other than the default, you'll need to
|
||||
set a few environment variables to point the toolchains to your installation path.
|
||||
* `vs2019_install = DRIVE:\path\to\Microsoft Visual Studio\2019\Community`, replacing `2019` and `Community` with your installed versions and replacing `DRIVE:` with the drive that Visual Studio is on. Often, this will be `C:`.
|
||||
* `WINDOWSSDKDIR = DRIVE:\path\to\Windows Kits\10`, replacing `DRIVE:` with the drive that Windows Kits is on. Often, this will be `C:`.
|
||||
* [Python for Windows (pywin32) Extensions](https://pypi.org/project/pywin32/#files)
|
||||
is also needed in order to run the build process.
|
||||
* [Node.js](https://nodejs.org/download/)
|
||||
* [Git](https://git-scm.com)
|
||||
* Debugging Tools for Windows of Windows SDK 10.0.15063.468 if you plan on
|
||||
|
||||
@@ -24,7 +24,7 @@ contribute:
|
||||
|
||||
## Asking for General Help
|
||||
|
||||
[The Electron website](https://electronjs.org/community) has a
|
||||
["Finding Support"](../tutorial/support.md#finding-support) has a
|
||||
list of resources for getting programming help, reporting security issues,
|
||||
contributing, and more. Please use the issue tracker for bugs only!
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ is only available in renderer processes.
|
||||
|
||||
If [sub-pixel anti-aliasing](https://alienryderflex.com/sub_pixel/) is deactivated, then fonts on LCD screens can look blurry. Example:
|
||||
|
||||

|
||||
![subpixel rendering example]
|
||||
|
||||
Sub-pixel anti-aliasing needs a non-transparent background of the layer containing the font glyphs. (See [this issue](https://github.com/electron/electron/issues/6344#issuecomment-420371918) for more info).
|
||||
|
||||
@@ -161,3 +161,4 @@ Notice that just setting the background in the CSS does not have the desired eff
|
||||
[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
|
||||
|
||||
0
docs/fiddles/communication/two-processes/.keep
Normal file
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<h1>Asynchronous messages</h1>
|
||||
<i>Supports: Win, macOS, Linux <span>|</span> Process: Both</i>
|
||||
<div>
|
||||
<div>
|
||||
<button id="async-msg">Ping</button>
|
||||
<span id="async-reply"></span>
|
||||
</div>
|
||||
<p>Using <code>ipc</code> to send messages between processes asynchronously is the preferred method since it will return when finished without blocking other operations in the same process.</p>
|
||||
|
||||
<p>This example sends a "ping" from this process (renderer) to the main process. The main process then replies with "pong".</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// You can also require other files to run in this process
|
||||
require('./renderer.js')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,29 @@
|
||||
const { app, BrowserWindow, ipcMain } = require('electron')
|
||||
|
||||
let mainWindow = null
|
||||
|
||||
function createWindow () {
|
||||
const windowOptions = {
|
||||
width: 600,
|
||||
height: 400,
|
||||
title: 'Asynchronous messages',
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
}
|
||||
|
||||
mainWindow = new BrowserWindow(windowOptions)
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
ipcMain.on('asynchronous-message', (event, arg) => {
|
||||
event.sender.send('asynchronous-reply', 'pong')
|
||||
})
|
||||
@@ -0,0 +1,12 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
const asyncMsgBtn = document.getElementById('async-msg')
|
||||
|
||||
asyncMsgBtn.addEventListener('click', () => {
|
||||
ipcRenderer.send('asynchronous-message', 'ping')
|
||||
})
|
||||
|
||||
ipcRenderer.on('asynchronous-reply', (event, arg) => {
|
||||
const message = `Asynchronous message reply: ${arg}`
|
||||
document.getElementById('async-reply').innerHTML = message
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<h1>Synchronous messages</h1>
|
||||
<i>Supports: Win, macOS, Linux <span>|</span> Process: Both</i>
|
||||
<div>
|
||||
<div>
|
||||
<button id="sync-msg">Ping</button>
|
||||
<span id="sync-reply"></span>
|
||||
</div>
|
||||
<p>You can use the <code>ipc</code> module to send synchronous messages between processes as well, but note that the synchronous nature of this method means that it <b>will block</b> other operations while completing its task.</p>
|
||||
|
||||
<p>This example sends a synchronous message, "ping", from this process (renderer) to the main process. The main process then replies with "pong".</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// You can also require other files to run in this process
|
||||
require('./renderer.js')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,29 @@
|
||||
const { app, BrowserWindow, ipcMain } = require('electron')
|
||||
|
||||
let mainWindow = null
|
||||
|
||||
function createWindow () {
|
||||
const windowOptions = {
|
||||
width: 600,
|
||||
height: 400,
|
||||
title: 'Synchronous Messages',
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
}
|
||||
|
||||
mainWindow = new BrowserWindow(windowOptions)
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
ipcMain.on('synchronous-message', (event, arg) => {
|
||||
event.returnValue = 'pong'
|
||||
})
|
||||
@@ -0,0 +1,9 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
const syncMsgBtn = document.getElementById('sync-msg')
|
||||
|
||||
syncMsgBtn.addEventListener('click', () => {
|
||||
const reply = ipcRenderer.sendSync('synchronous-message', 'ping')
|
||||
const message = `Synchronous message reply: ${reply}`
|
||||
document.getElementById('sync-reply').innerHTML = message
|
||||
})
|
||||
@@ -1,4 +1,5 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
startDrag: (fileName) => {
|
||||
|
||||
@@ -8,24 +8,20 @@ function createWindow () {
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('select-hid-device', (event, details, callback) => {
|
||||
//Add events to handle devices being added or removed before the callback on
|
||||
//`select-hid-device` is called.
|
||||
mainWindow.webContents.session.on('hid-device-added', (event, device) => {
|
||||
console.log('hid-device-added FIRED WITH', device)
|
||||
//Optionally update details.deviceList
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('hid-device-removed', (event, device) => {
|
||||
console.log('hid-device-removed FIRED WITH', device)
|
||||
//Optionally update details.deviceList
|
||||
})
|
||||
|
||||
event.preventDefault()
|
||||
if (details.deviceList && details.deviceList.length > 0) {
|
||||
callback(details.deviceList[0].deviceId)
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('hid-device-added', (event, device) => {
|
||||
console.log('hid-device-added FIRED WITH', device)
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('hid-device-removed', (event, device) => {
|
||||
console.log('hid-device-removed FIRED WITH', device)
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
|
||||
if (permission === 'hid' && details.securityOrigin === 'file:///') {
|
||||
return true
|
||||
|
||||
@@ -8,19 +8,6 @@ function createWindow () {
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {
|
||||
|
||||
//Add listeners to handle ports being added or removed before the callback for `select-serial-port`
|
||||
//is called.
|
||||
mainWindow.webContents.session.on('serial-port-added', (event, port) => {
|
||||
console.log('serial-port-added FIRED WITH', port)
|
||||
//Optionally update portList to add the new port
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('serial-port-removed', (event, port) => {
|
||||
console.log('serial-port-removed FIRED WITH', port)
|
||||
//Optionally update portList to remove the port
|
||||
})
|
||||
|
||||
event.preventDefault()
|
||||
if (portList && portList.length > 0) {
|
||||
callback(portList[0].portId)
|
||||
@@ -29,20 +16,24 @@ function createWindow () {
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('serial-port-added', (event, port) => {
|
||||
console.log('serial-port-added FIRED WITH', port)
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.on('serial-port-removed', (event, port) => {
|
||||
console.log('serial-port-removed FIRED WITH', port)
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
|
||||
if (permission === 'serial' && details.securityOrigin === 'file:///') {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.setDevicePermissionHandler((details) => {
|
||||
if (details.deviceType === 'serial' && details.origin === 'file://') {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<meta
|
||||
http-equiv="X-Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<title>Hello from Electron renderer!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello from Electron renderer!</h1>
|
||||
<p>👋</p>
|
||||
<p id="info"></p>
|
||||
</body>
|
||||
<script src="./renderer.js"></script>
|
||||
</html>
|
||||
@@ -1,26 +0,0 @@
|
||||
const { app, BrowserWindow } = require('electron');
|
||||
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
});
|
||||
|
||||
win.loadFile('index.html');
|
||||
};
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow();
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<meta
|
||||
http-equiv="X-Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<title>Hello from Electron renderer!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello from Electron renderer!</h1>
|
||||
<p>👋</p>
|
||||
<p id="info"></p>
|
||||
</body>
|
||||
<script src="./renderer.js"></script>
|
||||
</html>
|
||||
@@ -1,30 +0,0 @@
|
||||
const { app, BrowserWindow } = require('electron');
|
||||
const path = require('path');
|
||||
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
},
|
||||
});
|
||||
|
||||
win.loadFile('index.html');
|
||||
};
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow();
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
const { contextBridge } = require('electron');
|
||||
|
||||
contextBridge.exposeInMainWorld('versions', {
|
||||
node: () => process.versions.node,
|
||||
chrome: () => process.versions.chrome,
|
||||
electron: () => process.versions.electron,
|
||||
});
|
||||
@@ -1,2 +0,0 @@
|
||||
const information = document.getElementById('info');
|
||||
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`;
|
||||
@@ -91,7 +91,7 @@ An IPC system for communicating intra- or inter-process, and that's important
|
||||
because Chrome is keen on being able to split its work into separate processes
|
||||
or not, depending on memory pressures etc.
|
||||
|
||||
See https://chromium.googlesource.com/chromium/src/+/main/mojo/README.md
|
||||
See https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md
|
||||
|
||||
See also: [IPC](#ipc)
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 190 KiB |
BIN
docs/images/message-notification-renderer.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
docs/images/online-event-detection.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 70 KiB |
97
docs/images/tutorial-release-schedule.svg
Normal file
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" standalone="yes"?>
|
||||
<svg width="520" height="220" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<marker id="arrow" viewBox="-1 0 12 10" refX="10.5" refY="5" markerWidth="8" markerHeight="8" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10"/>
|
||||
</marker>
|
||||
<g transform="translate(0,40)">
|
||||
<!-- master -->
|
||||
<text x="60" y="30" text-anchor="end" alignment-baseline="middle">master</text>
|
||||
<path d="M70 30 H 500" stroke-width="2" stroke="black"/>
|
||||
<!-- v2.0 -->
|
||||
<g>
|
||||
<path d="M100 30 l 20 30 H 200" stroke-width="2" stroke="black" fill="transparent"/>
|
||||
<text x="110" y="60" text-anchor="end" alignment-baseline="middle">2.0</text>
|
||||
<circle cx="120" cy="60" r="5"/>
|
||||
<text x="110" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 120,60)">v2.0.0-beta0</text>
|
||||
<circle cx="200" cy="60" r="5"/>
|
||||
<text x="190" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 200,60)">v2.0.0</text>
|
||||
</g>
|
||||
<!-- v2.1 -->
|
||||
<g transform="translate(130,0)">
|
||||
<path d="M100 30 l 20 30 H 200" stroke-width="2" stroke="black" fill="transparent"/>
|
||||
<text x="110" y="60" text-anchor="end" alignment-baseline="middle">2.1</text>
|
||||
<circle cx="120" cy="60" r="5"/>
|
||||
<text x="110" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 120,60)">v2.1.0-beta0</text>
|
||||
<circle cx="160" cy="60" r="5"/>
|
||||
<text x="150" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 160,60)">v2.1.0-beta1</text>
|
||||
<circle cx="200" cy="60" r="5"/>
|
||||
<text x="190" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 200,60)">v2.1.0</text>
|
||||
</g>
|
||||
<!-- v3.0 -->
|
||||
<g transform="translate(260,0)">
|
||||
<path d="M100 30 l 20 30 H 200" stroke-width="2" stroke="black" fill="transparent"/>
|
||||
<text x="110" y="60" text-anchor="end" alignment-baseline="middle">3.0</text>
|
||||
<circle cx="120" cy="60" r="5"/>
|
||||
<text x="110" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 120,60)">v3.0.0-beta0</text>
|
||||
<circle cx="200" cy="60" r="5"/>
|
||||
<text x="190" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 200,60)">v3.0.0</text>
|
||||
</g>
|
||||
<!-- Bug fixes -->
|
||||
<g transform="translate(160,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">bug fix</text>
|
||||
<path d="M0 0 l0,30" marker-end="url(#arrow)" stroke-dasharray="2,2" stroke="#000"/>
|
||||
</g>
|
||||
<g transform="translate(260,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">bug fix</text>
|
||||
<path d="M0 0 l0,30" marker-end="url(#arrow)" stroke-dasharray="2,2" stroke="#000"/>
|
||||
</g>
|
||||
<g transform="translate(280,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">bug fix</text>
|
||||
<path d="M0 0 l0,30" marker-end="url(#arrow)" stroke-dasharray="2,2" stroke="#000"/>
|
||||
</g>
|
||||
<g transform="translate(400,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">bug fix</text>
|
||||
<path d="M0 0 l0,30" marker-end="url(#arrow)" stroke-dasharray="2,2" stroke="#000"/>
|
||||
</g>
|
||||
<g transform="translate(430,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">bug fix</text>
|
||||
<path d="M0 0 l0,30" marker-end="url(#arrow)" stroke-dasharray="2,2" stroke="#000"/>
|
||||
</g>
|
||||
<!-- Features -->
|
||||
<g transform="translate(130,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">feature</text>
|
||||
</g>
|
||||
<g transform="translate(200,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">feature</text>
|
||||
</g>
|
||||
<g transform="translate(340,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">feature</text>
|
||||
</g>
|
||||
<!-- Chromium update -->
|
||||
<g transform="translate(310,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)"><tspan>chromium</tspan><tspan dy="10" x="10">update</tspan></text>
|
||||
</g>
|
||||
<!-- Timeline -->
|
||||
<g transform="translate(100,160)">
|
||||
<text x="50" y="0" text-anchor="middle" alignment-baseline="text-after-edge">~1 week</text>
|
||||
<path d="M0 0 l0 10 l0 -5 H100l0 -5l0 10" stroke-width="2" stroke="black" fill="transparent"/>
|
||||
</g>
|
||||
<g transform="translate(230,160)">
|
||||
<text x="50" y="0" text-anchor="middle" alignment-baseline="text-after-edge">~1 week</text>
|
||||
<path d="M0 0 l0 10 l0 -5 H100l0 -5l0 10" stroke-width="2" stroke="black" fill="transparent"/>
|
||||
</g>
|
||||
<g transform="translate(360,160)">
|
||||
<text x="50" y="0" text-anchor="middle" alignment-baseline="text-after-edge">~1 week</text>
|
||||
<path d="M0 0 l0 10 l0 -5 H100l0 -5l0 10" stroke-width="2" stroke="black" fill="transparent"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 142 KiB |
@@ -1,26 +1,26 @@
|
||||
---
|
||||
title: 'Application Packaging'
|
||||
description: 'To distribute your app with Electron, you need to package and rebrand it. To do this, you can either use specialized tooling or manual approaches.'
|
||||
slug: application-distribution
|
||||
hide_title: false
|
||||
---
|
||||
# Application Distribution
|
||||
|
||||
To distribute your app with Electron, you need to package and rebrand it. To do this, you
|
||||
can either use specialized tooling or manual approaches.
|
||||
## Overview
|
||||
|
||||
To distribute your app with Electron, you need to package and rebrand it.
|
||||
To do this, you can either use specialized tooling or manual approaches.
|
||||
|
||||
## With tooling
|
||||
|
||||
There are a couple tools out there that exist to package and distribute your Electron app.
|
||||
We recommend using [Electron Forge](./forge-overview.md). You can check out
|
||||
its [documentation](https://www.electronforge.io) directly, or refer to the [Packaging and Distribution](./tutorial-5-packaging.md)
|
||||
part of the Electron tutorial.
|
||||
You can use the following tools to distribute your application:
|
||||
|
||||
## Manual packaging
|
||||
* [electron-forge](https://github.com/electron-userland/electron-forge)
|
||||
* [electron-builder](https://github.com/electron-userland/electron-builder)
|
||||
* [electron-packager](https://github.com/electron/electron-packager)
|
||||
|
||||
If you prefer the manual approach, there are 2 ways to distribute your application:
|
||||
These tools will take care of all the steps you need to take to end up with a
|
||||
distributable Electron application, such as bundling your application,
|
||||
rebranding the executable, and setting the right icons.
|
||||
|
||||
- With prebuilt binaries
|
||||
- With an app source code archive
|
||||
You can check the example of how to package your app with `electron-forge` in
|
||||
the [Quick Start guide](quick-start.md#package-and-distribute-your-application).
|
||||
|
||||
## Manual distribution
|
||||
|
||||
### With prebuilt binaries
|
||||
|
||||
@@ -29,19 +29,21 @@ binaries](https://github.com/electron/electron/releases). Next, the folder
|
||||
containing your app should be named `app` and placed in Electron's resources
|
||||
directory as shown in the following examples.
|
||||
|
||||
:::note
|
||||
The location of Electron's prebuilt binaries is indicated
|
||||
> *NOTE:* the location of Electron's prebuilt binaries is indicated
|
||||
with `electron/` in the examples below.
|
||||
:::
|
||||
|
||||
```plain title='macOS'
|
||||
*On macOS:*
|
||||
|
||||
```plaintext
|
||||
electron/Electron.app/Contents/Resources/app/
|
||||
├── package.json
|
||||
├── main.js
|
||||
└── index.html
|
||||
```
|
||||
|
||||
```plain title='Windows and Linux'
|
||||
*On Windows and Linux:*
|
||||
|
||||
```plaintext
|
||||
electron/resources/app
|
||||
├── package.json
|
||||
├── main.js
|
||||
@@ -52,7 +54,7 @@ Then execute `Electron.app` on macOS, `electron` on Linux, or `electron.exe`
|
||||
on Windows, and Electron will start as your app. The `electron` directory
|
||||
will then be your distribution to deliver to users.
|
||||
|
||||
### With an app source code archive (asar)
|
||||
### With an app source code archive
|
||||
|
||||
Instead of shipping your app by copying all of its source files, you can
|
||||
package your app into an [asar] archive to improve the performance of reading
|
||||
@@ -63,12 +65,16 @@ To use an `asar` archive to replace the `app` folder, you need to rename the
|
||||
archive to `app.asar`, and put it under Electron's resources directory like
|
||||
below, and Electron will then try to read the archive and start from it.
|
||||
|
||||
```plain title='macOS'
|
||||
*On macOS:*
|
||||
|
||||
```plaintext
|
||||
electron/Electron.app/Contents/Resources/
|
||||
└── app.asar
|
||||
```
|
||||
|
||||
```plain title='Windows'
|
||||
*On Windows and Linux:*
|
||||
|
||||
```plaintext
|
||||
electron/resources/
|
||||
└── app.asar
|
||||
```
|
||||
@@ -81,44 +87,47 @@ You can find more details on how to use `asar` in the
|
||||
After bundling your app into Electron, you will want to rebrand Electron
|
||||
before distributing it to users.
|
||||
|
||||
- **Windows:** You can rename `electron.exe` to any name you like, and edit
|
||||
its icon and other information with tools like [rcedit](https://github.com/electron/rcedit).
|
||||
- **Linux:** You can rename the `electron` executable to any name you like.
|
||||
- **macOS:** You can rename `Electron.app` to any name you want, and you also have to rename
|
||||
the `CFBundleDisplayName`, `CFBundleIdentifier` and `CFBundleName` fields in the
|
||||
following files:
|
||||
#### macOS
|
||||
|
||||
- `Electron.app/Contents/Info.plist`
|
||||
- `Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist`
|
||||
You can rename `Electron.app` to any name you want, and you also have to rename
|
||||
the `CFBundleDisplayName`, `CFBundleIdentifier` and `CFBundleName` fields in the
|
||||
following files:
|
||||
|
||||
You can also rename the helper app to avoid showing `Electron Helper` in the
|
||||
Activity Monitor, but make sure you have renamed the helper app's executable
|
||||
file's name.
|
||||
* `Electron.app/Contents/Info.plist`
|
||||
* `Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist`
|
||||
|
||||
The structure of a renamed app would be like:
|
||||
You can also rename the helper app to avoid showing `Electron Helper` in the
|
||||
Activity Monitor, but make sure you have renamed the helper app's executable
|
||||
file's name.
|
||||
|
||||
```plain
|
||||
The structure of a renamed app would be like:
|
||||
|
||||
```plaintext
|
||||
MyApp.app/Contents
|
||||
├── Info.plist
|
||||
├── MacOS/
|
||||
│ └── MyApp
|
||||
│ └── MyApp
|
||||
└── Frameworks/
|
||||
└── MyApp Helper.app
|
||||
├── Info.plist
|
||||
└── MacOS/
|
||||
└── MyApp Helper
|
||||
└── MyApp Helper
|
||||
```
|
||||
|
||||
:::note
|
||||
#### Windows
|
||||
|
||||
it is also possible to rebrand Electron by changing the product name and
|
||||
You can rename `electron.exe` to any name you like, and edit its icon and other
|
||||
information with tools like [rcedit](https://github.com/electron/rcedit).
|
||||
|
||||
#### Linux
|
||||
|
||||
You can rename the `electron` executable to any name you like.
|
||||
|
||||
### Rebranding by rebuilding Electron from source
|
||||
|
||||
It is also possible to rebrand Electron by changing the product name and
|
||||
building it from source. To do this you need to set the build argument
|
||||
corresponding to the product name (`electron_product_name = "YourProductName"`)
|
||||
in the `args.gn` file and rebuild.
|
||||
|
||||
Keep in mind this is not recommended as setting up the environment to compile
|
||||
from source is not trivial and takes significant time.
|
||||
|
||||
:::
|
||||
|
||||
[asar]: https://github.com/electron/asar
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
---
|
||||
title: ASAR Archives
|
||||
description: What is ASAR archive and how does it affect the application.
|
||||
slug: asar-archives
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
After creating an [application distribution](application-distribution.md), the
|
||||
app's source code are usually bundled into an [ASAR
|
||||
archive](https://github.com/electron/asar), which is a simple extensive archive
|
||||
format designed for Electron apps. By bundling the app we can mitigate issues
|
||||
around long path names on Windows, speed up `require` and conceal your source
|
||||
code from cursory inspection.
|
||||
|
||||
The bundled app runs in a virtual file system and most APIs would just work
|
||||
normally, but for some cases you might want to work on ASAR archives explicitly
|
||||
due to a few caveats.
|
||||
|
||||
## Using ASAR Archives
|
||||
|
||||
In Electron there are two sets of APIs: Node APIs provided by Node.js and Web
|
||||
APIs provided by Chromium. Both APIs support reading files from ASAR archives.
|
||||
|
||||
### Node API
|
||||
|
||||
With special patches in Electron, Node APIs like `fs.readFile` and `require`
|
||||
treat ASAR archives as virtual directories, and the files in it as normal
|
||||
files in the filesystem.
|
||||
|
||||
For example, suppose we have an `example.asar` archive under `/path/to`:
|
||||
|
||||
```sh
|
||||
$ asar list /path/to/example.asar
|
||||
/app.js
|
||||
/file.txt
|
||||
/dir/module.js
|
||||
/static/index.html
|
||||
/static/main.css
|
||||
/static/jquery.min.js
|
||||
```
|
||||
|
||||
Read a file in the ASAR archive:
|
||||
|
||||
```javascript
|
||||
const fs = require('fs')
|
||||
fs.readFileSync('/path/to/example.asar/file.txt')
|
||||
```
|
||||
|
||||
List all files under the root of the archive:
|
||||
|
||||
```javascript
|
||||
const fs = require('fs')
|
||||
fs.readdirSync('/path/to/example.asar')
|
||||
```
|
||||
|
||||
Use a module from the archive:
|
||||
|
||||
```javascript
|
||||
require('./path/to/example.asar/dir/module.js')
|
||||
```
|
||||
|
||||
You can also display a web page in an ASAR archive with `BrowserWindow`:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
|
||||
win.loadURL('file:///path/to/example.asar/static/index.html')
|
||||
```
|
||||
|
||||
### Web API
|
||||
|
||||
In a web page, files in an archive can be requested with the `file:` protocol.
|
||||
Like the Node API, ASAR archives are treated as directories.
|
||||
|
||||
For example, to get a file with `$.get`:
|
||||
|
||||
```html
|
||||
<script>
|
||||
let $ = require('./jquery.min.js')
|
||||
$.get('file:///path/to/example.asar/file.txt', (data) => {
|
||||
console.log(data)
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
### Treating an ASAR archive as a Normal File
|
||||
|
||||
For some cases like verifying the ASAR archive's checksum, we need to read the
|
||||
content of an ASAR archive as a file. For this purpose you can use the built-in
|
||||
`original-fs` module which provides original `fs` APIs without `asar` support:
|
||||
|
||||
```javascript
|
||||
const originalFs = require('original-fs')
|
||||
originalFs.readFileSync('/path/to/example.asar')
|
||||
```
|
||||
|
||||
You can also set `process.noAsar` to `true` to disable the support for `asar` in
|
||||
the `fs` module:
|
||||
|
||||
```javascript
|
||||
const fs = require('fs')
|
||||
process.noAsar = true
|
||||
fs.readFileSync('/path/to/example.asar')
|
||||
```
|
||||
|
||||
## Limitations of the Node API
|
||||
|
||||
Even though we tried hard to make ASAR archives in the Node API work like
|
||||
directories as much as possible, there are still limitations due to the
|
||||
low-level nature of the Node API.
|
||||
|
||||
### Archives Are Read-only
|
||||
|
||||
The archives can not be modified so all Node APIs that can modify files will not
|
||||
work with ASAR archives.
|
||||
|
||||
### Working Directory Can Not Be Set to Directories in Archive
|
||||
|
||||
Though ASAR archives are treated as directories, there are no actual
|
||||
directories in the filesystem, so you can never set the working directory to
|
||||
directories in ASAR archives. Passing them as the `cwd` option of some APIs
|
||||
will also cause errors.
|
||||
|
||||
### Extra Unpacking on Some APIs
|
||||
|
||||
Most `fs` APIs can read a file or get a file's information from ASAR archives
|
||||
without unpacking, but for some APIs that rely on passing the real file path to
|
||||
underlying system calls, Electron will extract the needed file into a
|
||||
temporary file and pass the path of the temporary file to the APIs to make them
|
||||
work. This adds a little overhead for those APIs.
|
||||
|
||||
APIs that requires extra unpacking are:
|
||||
|
||||
* `child_process.execFile`
|
||||
* `child_process.execFileSync`
|
||||
* `fs.open`
|
||||
* `fs.openSync`
|
||||
* `process.dlopen` - Used by `require` on native modules
|
||||
|
||||
### Fake Stat Information of `fs.stat`
|
||||
|
||||
The `Stats` object returned by `fs.stat` and its friends on files in `asar`
|
||||
archives is generated by guessing, because those files do not exist on the
|
||||
filesystem. So you should not trust the `Stats` object except for getting file
|
||||
size and checking file type.
|
||||
|
||||
### Executing Binaries Inside ASAR archive
|
||||
|
||||
There are Node APIs that can execute binaries like `child_process.exec`,
|
||||
`child_process.spawn` and `child_process.execFile`, but only `execFile` is
|
||||
supported to execute binaries inside ASAR archive.
|
||||
|
||||
This is because `exec` and `spawn` accept `command` instead of `file` as input,
|
||||
and `command`s are executed under shell. There is no reliable way to determine
|
||||
whether a command uses a file in asar archive, and even if we do, we can not be
|
||||
sure whether we can replace the path in command without side effects.
|
||||
|
||||
## Adding Unpacked Files to ASAR archives
|
||||
|
||||
As stated above, some Node APIs will unpack the file to the filesystem when
|
||||
called. Apart from the performance issues, various anti-virus scanners might
|
||||
be triggered by this behavior.
|
||||
|
||||
As a workaround, you can leave various files unpacked using the `--unpack` option.
|
||||
In the following example, shared libraries of native Node.js modules will not be
|
||||
packed:
|
||||
|
||||
```sh
|
||||
$ asar pack app app.asar --unpack *.node
|
||||
```
|
||||
|
||||
After running the command, you will notice that a folder named `app.asar.unpacked`
|
||||
was created together with the `app.asar` file. It contains the unpacked files
|
||||
and should be shipped together with the `app.asar` archive.
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
title: 'ASAR Integrity'
|
||||
description: 'An experimental feature that ensures the validity of ASAR contents at runtime.'
|
||||
slug: asar-integrity
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
## Platform Support
|
||||
|
||||
Currently ASAR integrity checking is only supported on macOS.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Electron Forge / Electron Packager
|
||||
|
||||
If you are using `>= electron-packager@15.4.0` or `>= @electron-forge/core@6.0.0-beta.61` then all these requirements are met for you automatically and you can skip to [Toggling the Fuse](#toggling-the-fuse).
|
||||
|
||||
### Other build systems
|
||||
|
||||
In order to enable ASAR integrity checking you need to ensure that your `app.asar` file was generated by a version of the `asar` npm package that supports asar integrity. Support was introduced in version `3.1.0`.
|
||||
|
||||
Your must then populate a valid `ElectronAsarIntegrity` dictionary block in your packaged apps `Info.plist`. An example is included below.
|
||||
|
||||
```plist
|
||||
<key>ElectronAsarIntegrity</key>
|
||||
<dict>
|
||||
<key>Resources/app.asar</key>
|
||||
<dict>
|
||||
<key>algorithm</key>
|
||||
<string>SHA256</string>
|
||||
<key>hash</key>
|
||||
<string>9d1f61ea03c4bb62b4416387a521101b81151da0cfbe18c9f8c8b818c5cebfac</string>
|
||||
</dict>
|
||||
</dict>
|
||||
```
|
||||
|
||||
Valid `algorithm` values are currently `SHA256` only. The `hash` is a hash of the ASAR header using the given algorithm. The `asar` package exposes a `getRawHeader` method whose result can then be hashed to generate this value.
|
||||
|
||||
## Toggling the Fuse
|
||||
|
||||
ASAR integrity checking is currently disabled by default and can be enabled by toggling a fuse. See [Electron Fuses](fuses.md) for more information on what Electron Fuses are and how they work. When enabling this fuse you typically also want to enable the `onlyLoadAppFromAsar` fuse otherwise the validity checking can be bypassed via the Electron app code search path.
|
||||
|
||||
```js
|
||||
require('@electron/fuses').flipFuses(
|
||||
// E.g. /a/b/Foo.app
|
||||
pathToPackagedApp,
|
||||
{
|
||||
version: FuseVersion.V1,
|
||||
[FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true,
|
||||
[FuseV1Options.OnlyLoadAppFromAsar]: true
|
||||
}
|
||||
)
|
||||
```
|
||||
@@ -26,8 +26,10 @@ beginners, using a command line tool is likely to be helpful*.
|
||||
|
||||
## electron-forge
|
||||
|
||||
Electron Forge is a tool for packaging and publishing Electron applications. It unifies Electron's tooling ecosystem
|
||||
into a single extensible interface so that anyone can jump right into making Electron apps.
|
||||
A "complete tool for building modern Electron applications". Electron Forge
|
||||
unifies the existing (and well maintained) build tools for Electron development
|
||||
into a cohesive package so that anyone can jump right in to Electron
|
||||
development.
|
||||
|
||||
Forge comes with [a ready-to-use template](https://electronforge.io/templates) using Webpack as a bundler. It includes an example typescript configuration and provides two configuration files to enable easy customization. It uses the same core modules used by the
|
||||
greater Electron community (like [`electron-packager`](https://github.com/electron/electron-packager)) –
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
---
|
||||
title: 'Code Signing'
|
||||
description: 'Code signing is a security technology that you use to certify that an app was created by you.'
|
||||
slug: code-signing
|
||||
hide_title: false
|
||||
---
|
||||
# Code Signing
|
||||
|
||||
Code signing is a security technology that you use to certify that an app was
|
||||
created by you. You should sign your application so it does not trigger any
|
||||
operating system security checks.
|
||||
created by you.
|
||||
|
||||
On macOS, the system can detect any change to the app, whether the change is
|
||||
On macOS the system can detect any change to the app, whether the change is
|
||||
introduced accidentally or by malicious code.
|
||||
|
||||
On Windows, the system assigns a trust level to your code signing certificate
|
||||
which if you don't have, or if your trust level is low, will cause security
|
||||
dialogs to appear when users start using your application. Trust level builds
|
||||
dialogs to appear when users start using your application. Trust level builds
|
||||
over time so it's better to start code signing as early as possible.
|
||||
|
||||
While it is possible to distribute unsigned apps, it is not recommended. Both
|
||||
@@ -22,19 +16,20 @@ Windows and macOS will, by default, prevent either the download or the execution
|
||||
of unsigned applications. Starting with macOS Catalina (version 10.15), users
|
||||
have to go through multiple manual steps to open unsigned applications.
|
||||
|
||||

|
||||

|
||||
|
||||
As you can see, users get two options: Move the app straight to the trash or
|
||||
cancel running it. You don't want your users to see that dialog.
|
||||
|
||||
If you are building an Electron app that you intend to package and distribute,
|
||||
it should be code signed.
|
||||
it should be code-signed.
|
||||
|
||||
## Signing & notarizing macOS builds
|
||||
# Signing & notarizing macOS builds
|
||||
|
||||
Properly preparing macOS applications for release requires two steps. First, the
|
||||
app needs to be code signed. Then, the app needs to be uploaded to Apple for a
|
||||
process called **notarization**, where automated systems will further verify that
|
||||
Properly preparing macOS applications for release requires two steps: First, the
|
||||
app needs to be code-signed. Then, the app needs to be uploaded to Apple for a
|
||||
process called "notarization", where automated systems will further verify that
|
||||
your app isn't doing anything to endanger its users.
|
||||
|
||||
To start the process, ensure that you fulfill the requirements for signing and
|
||||
@@ -47,23 +42,99 @@ notarizing your app:
|
||||
Electron's ecosystem favors configuration and freedom, so there are multiple
|
||||
ways to get your application signed and notarized.
|
||||
|
||||
### Using Electron Forge
|
||||
## `electron-forge`
|
||||
|
||||
If you're using Electron's favorite build tool, getting your application signed
|
||||
and notarized requires a few additions to your configuration. [Forge](https://electronforge.io) is a
|
||||
collection of the official Electron tools, using [`electron-packager`],
|
||||
[`electron-osx-sign`], and [`electron-notarize`] under the hood.
|
||||
|
||||
Detailed instructions on how to configure your application can be found in the [Electron Forge Code Signing Tutorial](https://www.electronforge.io/guides/code-signing/code-signing-macos).
|
||||
Let's take a look at an example configuration with all required fields. Not all
|
||||
of them are required: the tools will be clever enough to automatically find a
|
||||
suitable `identity`, for instance, but we recommend that you are explicit.
|
||||
|
||||
### Using Electron Packager
|
||||
```json
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "0.0.1",
|
||||
"config": {
|
||||
"forge": {
|
||||
"packagerConfig": {
|
||||
"osxSign": {
|
||||
"identity": "Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)",
|
||||
"hardened-runtime": true,
|
||||
"entitlements": "entitlements.plist",
|
||||
"entitlements-inherit": "entitlements.plist",
|
||||
"signature-flags": "library"
|
||||
},
|
||||
"osxNotarize": {
|
||||
"appleId": "felix@felix.fun",
|
||||
"appleIdPassword": "my-apple-id-password",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you're not using an integrated build pipeline like Forge, you
|
||||
The `plist` file referenced here needs the following macOS-specific entitlements
|
||||
to assure the Apple security mechanisms that your app is doing these things
|
||||
without meaning any harm:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Note that up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
|
||||
as well. However, it should not be used anymore if it can be avoided.
|
||||
|
||||
To see all of this in action, check out Electron Fiddle's source code,
|
||||
[especially its `electron-forge` configuration
|
||||
file](https://github.com/electron/fiddle/blob/master/forge.config.js).
|
||||
|
||||
If you plan to access the microphone or camera within your app using Electron's APIs, you'll also
|
||||
need to add the following entitlements:
|
||||
|
||||
```xml
|
||||
<key>com.apple.security.device.audio-input</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.camera</key>
|
||||
<true/>
|
||||
```
|
||||
|
||||
If these are not present in your app's entitlements when you invoke, for example:
|
||||
|
||||
```js
|
||||
const { systemPreferences } = require('electron')
|
||||
|
||||
const microphone = systemPreferences.askForMediaAccess('microphone')
|
||||
```
|
||||
|
||||
Your app may crash. See the Resource Access section in [Hardened Runtime](https://developer.apple.com/documentation/security/hardened_runtime) for more information and entitlements you may need.
|
||||
|
||||
## `electron-builder`
|
||||
|
||||
Electron Builder comes with a custom solution for signing your application. You
|
||||
can find [its documentation here](https://www.electron.build/code-signing).
|
||||
|
||||
## `electron-packager`
|
||||
|
||||
If you're not using an integrated build pipeline like Forge or Builder, you
|
||||
are likely using [`electron-packager`], which includes [`electron-osx-sign`] and
|
||||
[`electron-notarize`].
|
||||
|
||||
If you're using Packager's API, you can pass [in configuration that both signs
|
||||
and notarizes your application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html).
|
||||
and notarizes your
|
||||
application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html).
|
||||
|
||||
```js
|
||||
const packager = require('electron-packager')
|
||||
@@ -84,11 +155,11 @@ packager({
|
||||
})
|
||||
```
|
||||
|
||||
The `entitlements.plist` file referenced here needs the following macOS-specific entitlements
|
||||
The `plist` file referenced here needs the following macOS-specific entitlements
|
||||
to assure the Apple security mechanisms that your app is doing these things
|
||||
without meaning any harm:
|
||||
|
||||
```xml title="entitlements.plist"
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
@@ -104,11 +175,11 @@ without meaning any harm:
|
||||
Up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
|
||||
as well. However, it should not be used anymore if it can be avoided.
|
||||
|
||||
### Signing Mac App Store applications
|
||||
## Mac App Store
|
||||
|
||||
See the [Mac App Store Guide].
|
||||
|
||||
## Signing Windows builds
|
||||
# Signing Windows builds
|
||||
|
||||
Before signing Windows builds, you must do the following:
|
||||
|
||||
@@ -119,111 +190,31 @@ Before signing Windows builds, you must do the following:
|
||||
You can get a code signing certificate from a lot of resellers. Prices vary, so
|
||||
it may be worth your time to shop around. Popular resellers include:
|
||||
|
||||
- [digicert](https://www.digicert.com/code-signing/microsoft-authenticode.htm)
|
||||
- [Sectigo](https://sectigo.com/ssl-certificates-tls/code-signing)
|
||||
- Amongst others, please shop around to find one that suits your needs! 😄
|
||||
* [digicert](https://www.digicert.com/code-signing/microsoft-authenticode.htm)
|
||||
* [Sectigo](https://sectigo.com/ssl-certificates-tls/code-signing)
|
||||
* Amongst others, please shop around to find one that suits your needs, Google
|
||||
is your friend 😄
|
||||
|
||||
:::caution Keep your certificate password private
|
||||
Your certificate password should be a **secret**. Do not share it publicly or
|
||||
commit it to your source code.
|
||||
:::
|
||||
There are a number of tools for signing your packaged app:
|
||||
|
||||
### Using Electron Forge
|
||||
* [`electron-winstaller`] will generate an installer for windows and sign it for
|
||||
you
|
||||
* [`electron-forge`] can sign installers it generates through the
|
||||
Squirrel.Windows or MSI targets.
|
||||
* [`electron-builder`] can sign some of its windows targets
|
||||
|
||||
Electron Forge is the recommended way to sign your `Squirrel.Windows` and `WiX MSI` installers. Detailed instructions on how to configure your application can be found in the [Electron Forge Code Signing Tutorial](https://www.electronforge.io/guides/code-signing/code-signing-macos).
|
||||
|
||||
### Using electron-winstaller (Squirrel.Windows)
|
||||
|
||||
[`electron-winstaller`] is a package that can generate Squirrel.Windows installers for your
|
||||
Electron app. This is the tool used under the hood by Electron Forge's
|
||||
[Squirrel.Windows Maker][maker-squirrel]. If you're not using Electron Forge and want to use
|
||||
`electron-winstaller` directly, use the `certificateFile` and `certificatePassword` configuration
|
||||
options when creating your installer.
|
||||
|
||||
```js {10-11}
|
||||
const electronInstaller = require('electron-winstaller')
|
||||
// NB: Use this syntax within an async function, Node does not have support for
|
||||
// top-level await as of Node 12.
|
||||
try {
|
||||
await electronInstaller.createWindowsInstaller({
|
||||
appDirectory: '/tmp/build/my-app-64',
|
||||
outputDirectory: '/tmp/build/installer64',
|
||||
authors: 'My App Inc.',
|
||||
exe: 'myapp.exe',
|
||||
certificateFile: './cert.pfx',
|
||||
certificatePassword: 'this-is-a-secret',
|
||||
})
|
||||
console.log('It worked!')
|
||||
} catch (e) {
|
||||
console.log(`No dice: ${e.message}`)
|
||||
}
|
||||
```
|
||||
|
||||
For full configuration options, check out the [`electron-winstaller`] repository!
|
||||
|
||||
### Using electron-wix-msi (WiX MSI)
|
||||
|
||||
[`electron-wix-msi`] is a package that can generate MSI installers for your
|
||||
Electron app. This is the tool used under the hood by Electron Forge's [MSI Maker][maker-msi].
|
||||
|
||||
If you're not using Electron Forge and want to use `electron-wix-msi` directly, use the
|
||||
`certificateFile` and `certificatePassword` configuration options
|
||||
or pass in parameters directly to [SignTool.exe] with the `signWithParams` option.
|
||||
|
||||
```js {12-13}
|
||||
import { MSICreator } from 'electron-wix-msi'
|
||||
|
||||
// Step 1: Instantiate the MSICreator
|
||||
const msiCreator = new MSICreator({
|
||||
appDirectory: '/path/to/built/app',
|
||||
description: 'My amazing Kitten simulator',
|
||||
exe: 'kittens',
|
||||
name: 'Kittens',
|
||||
manufacturer: 'Kitten Technologies',
|
||||
version: '1.1.2',
|
||||
outputDirectory: '/path/to/output/folder',
|
||||
certificateFile: './cert.pfx',
|
||||
certificatePassword: 'this-is-a-secret',
|
||||
})
|
||||
|
||||
// Step 2: Create a .wxs template file
|
||||
const supportBinaries = await msiCreator.create()
|
||||
|
||||
// 🆕 Step 2a: optionally sign support binaries if you
|
||||
// sign you binaries as part of of your packaging script
|
||||
supportBinaries.forEach(async (binary) => {
|
||||
// Binaries are the new stub executable and optionally
|
||||
// the Squirrel auto updater.
|
||||
await signFile(binary)
|
||||
})
|
||||
|
||||
// Step 3: Compile the template to a .msi file
|
||||
await msiCreator.compile()
|
||||
```
|
||||
|
||||
For full configuration options, check out the [`electron-wix-msi`] repository!
|
||||
|
||||
### Using Electron Builder
|
||||
|
||||
Electron Builder comes with a custom solution for signing your application. You
|
||||
can find [its documentation here](https://www.electron.build/code-signing).
|
||||
|
||||
### Signing Windows Store applications
|
||||
## Windows Store
|
||||
|
||||
See the [Windows Store Guide].
|
||||
|
||||
[apple developer program]: https://developer.apple.com/programs/
|
||||
[Apple Developer Program]: https://developer.apple.com/programs/
|
||||
[`electron-builder`]: https://github.com/electron-userland/electron-builder
|
||||
[`electron-forge`]: https://github.com/electron-userland/electron-forge
|
||||
[`electron-osx-sign`]: https://github.com/electron-userland/electron-osx-sign
|
||||
[`electron-packager`]: https://github.com/electron/electron-packager
|
||||
[`electron-notarize`]: https://github.com/electron/electron-notarize
|
||||
[`electron-winstaller`]: https://github.com/electron/windows-installer
|
||||
[`electron-wix-msi`]: https://github.com/felixrieseberg/electron-wix-msi
|
||||
[xcode]: https://developer.apple.com/xcode
|
||||
[Xcode]: https://developer.apple.com/xcode
|
||||
[signing certificates]: https://github.com/electron/electron-osx-sign/wiki/1.-Getting-Started#certificates
|
||||
[mac app store guide]: ./mac-app-store-submission-guide.md
|
||||
[windows store guide]: ./windows-store-guide.md
|
||||
[maker-squirrel]: https://www.electronforge.io/config/makers/squirrel.windows
|
||||
[maker-msi]: https://www.electronforge.io/config/makers/wix-msi
|
||||
[signtool.exe]: https://docs.microsoft.com/en-us/dotnet/framework/tools/signtool-exe
|
||||
[Mac App Store Guide]: mac-app-store-submission-guide.md
|
||||
[Windows Store Guide]: windows-store-guide.md
|
||||
|
||||
@@ -36,10 +36,8 @@ the WebHID API:
|
||||
can be used to select a HID device when a call to
|
||||
`navigator.hid.requestDevice` is made. Additionally the [`hid-device-added`](../api/session.md#event-hid-device-added)
|
||||
and [`hid-device-removed`](../api/session.md#event-hid-device-removed) events
|
||||
on the Session can be used to handle devices being plugged in or unplugged
|
||||
when handling the `select-hid-device` event.
|
||||
**Note:** These events only fire until the callback from `select-hid-device`
|
||||
is called. They are not intended to be used as a generic hid device listener.
|
||||
on the Session can be used to handle devices being plugged in or unplugged during the
|
||||
`navigator.hid.requestDevice` process.
|
||||
* [`ses.setDevicePermissionHandler(handler)`](../api/session.md#sessetdevicepermissionhandlerhandler)
|
||||
can be used to provide default permissioning to devices without first calling
|
||||
for permission to devices via `navigator.hid.requestDevice`. Additionally,
|
||||
@@ -84,11 +82,8 @@ There are several additional APIs for working with the Web Serial API:
|
||||
|
||||
* The [`serial-port-added`](../api/session.md#event-serial-port-added)
|
||||
and [`serial-port-removed`](../api/session.md#event-serial-port-removed) events
|
||||
on the Session can be used to handle devices being plugged in or unplugged
|
||||
when handling the `select-serial-port` event.
|
||||
**Note:** These events only fire until the callback from `select-serial-port`
|
||||
is called. They are not intended to be used as a generic serial port
|
||||
listener.
|
||||
on the Session can be used to handle devices being plugged in or unplugged during the
|
||||
`navigator.serial.requestPort` process.
|
||||
* [`ses.setDevicePermissionHandler(handler)`](../api/session.md#sessetdevicepermissionhandlerhandler)
|
||||
can be used to provide default permissioning to devices without first calling
|
||||
for permission to devices via `navigator.serial.requestPort`. Additionally,
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
---
|
||||
title: 'Distribution Overview'
|
||||
description: 'To distribute your app with Electron, you need to package and rebrand it. To do this, you can either use specialized tooling or manual approaches.'
|
||||
slug: distribution-overview
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
Once your app is ready for production, there are a couple steps you need to take before
|
||||
you can deliver it to your users.
|
||||
|
||||
## Packaging
|
||||
|
||||
To distribute your app with Electron, you need to package all your resources and assets
|
||||
into an executable and rebrand it. To do this, you can either use specialized tooling like Electron Forge
|
||||
or do it manually. See the [Application Packaging][application-packaging] tutorial
|
||||
for more information.
|
||||
|
||||
## Code signing
|
||||
|
||||
Code signing is a security technology that you use to certify that an app was
|
||||
created by you. You should sign your application so it does not trigger the
|
||||
security checks of your user's operating system.
|
||||
|
||||
To get started with each operating system's code signing process, please read the
|
||||
[Code Signing][code-signing] docs.
|
||||
|
||||
## Publishing
|
||||
|
||||
Once your app is packaged and signed, you can freely distribute your app directly
|
||||
to users by uploading your installers online.
|
||||
|
||||
To reach more users, you can also choose to upload your app to each operating system's
|
||||
digital distribution platform (i.e. app store). These require another build step aside
|
||||
from your direct download app. For more information, check out each individual app store guide:
|
||||
|
||||
- [Mac App Store][mac-app]
|
||||
- [Windows Store][windows-store]
|
||||
- [Snapcraft (Linux)][snapcraft]
|
||||
|
||||
## Updating
|
||||
|
||||
Electron's auto-updater allows you to deliver application updates to users
|
||||
without forcing them to manually download new versions of your application.
|
||||
Check out the [Updating Applications][updates] guide for details on implementing automatic updates
|
||||
with Electron.
|
||||
|
||||
<!-- Link labels -->
|
||||
|
||||
[application-packaging]: ./application-distribution.md
|
||||
[code-signing]: ./code-signing.md
|
||||
[mac-app]: ./mac-app-store-submission-guide.md
|
||||
[windows-store]: ./windows-store-guide.md
|
||||
[snapcraft]: ./snapcraft.md
|
||||
[updates]: ./updates.md
|
||||
@@ -1,102 +1,30 @@
|
||||
# Electron Releases
|
||||
# Electron Release Timelines
|
||||
|
||||
Electron frequently releases major versions alongside every other Chromium release.
|
||||
This document focuses on the release cadence and version support policy.
|
||||
For a more in-depth guide on our git branches and how Electron uses semantic versions,
|
||||
check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
Special notes:
|
||||
|
||||
## Timeline
|
||||
|
||||
| Electron | Alpha | Beta | Stable | Chrome | Node | Supported |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- | ---- |
|
||||
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | M61 | v8.9 | 🚫 |
|
||||
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | M66 | v10.2 | 🚫 |
|
||||
| 4.0.0 | -- | 2018-Oct-11 | 2018-Dec-20 | M69 | v10.11 | 🚫 |
|
||||
| 5.0.0 | -- | 2019-Jan-22 | 2019-Apr-24 | M73 | v12.0 | 🚫 |
|
||||
| 6.0.0 | -- | 2019-May-01 | 2019-Jul-30 | M76 | v12.4 | 🚫 |
|
||||
| 7.0.0 | -- | 2019-Aug-01 | 2019-Oct-22 | M78 | v12.8 | 🚫 |
|
||||
| 8.0.0 | -- | 2019-Oct-24 | 2020-Feb-04 | M80 | v12.13 | 🚫 |
|
||||
| 9.0.0 | -- | 2020-Feb-06 | 2020-May-19 | M83 | v12.14 | 🚫 |
|
||||
| 10.0.0 | -- | 2020-May-21 | 2020-Aug-25 | M85 | v12.16 | 🚫 |
|
||||
| 11.0.0 | -- | 2020-Aug-27 | 2020-Nov-17 | M87 | v12.18 | 🚫 |
|
||||
| 12.0.0 | -- | 2020-Nov-19 | 2021-Mar-02 | M89 | v14.16 | 🚫 |
|
||||
| 13.0.0 | -- | 2021-Mar-04 | 2021-May-25 | M91 | v14.16 | 🚫 |
|
||||
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | M93 | v14.17 | 🚫 |
|
||||
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | M94 | v16.5 | 🚫 |
|
||||
| 16.0.0 | 2021-Sep-23 | 2021-Oct-20 | 2021-Nov-16 | M96 | v16.9 | 🚫 |
|
||||
| 17.0.0 | 2021-Nov-18 | 2022-Jan-06 | 2022-Feb-01 | M98 | v16.13 | 🚫 |
|
||||
| 18.0.0 | 2022-Feb-03 | 2022-Mar-03 | 2022-Mar-29 | M100 | v16.13 | ✅ |
|
||||
| 19.0.0 | 2022-Mar-31 | 2022-Apr-26 | 2022-May-24 | M102 | v16.14 | ✅ |
|
||||
| 20.0.0 | 2022-May-26 | 2022-Jun-21 | 2022-Aug-02 | M104 | v16.15 | ✅ |
|
||||
| 21.0.0 | 2022-Aug-04 | 2022-Aug-30 | 2022-Sep-27 | M106 | TBD | ✅ |
|
||||
|
||||
**Notes:**
|
||||
|
||||
* The `-alpha.1`, `-beta.1`, and `stable` dates are our solid release dates.
|
||||
* We strive for weekly alpha/beta releases, but we often release more than scheduled.
|
||||
* The `-beta.1` and `stable` dates are our solid release dates.
|
||||
* We strive for weekly beta releases, however we often release more betas than scheduled.
|
||||
* All dates are our goals but there may be reasons for adjusting the stable deadline, such as security bugs.
|
||||
* Take a look at the [5.0.0 Timeline blog post](https://electronjs.org/blog/electron-5-0-timeline) for info about publicizing our release dates.
|
||||
* Since Electron 6.0, we've been targeting every other Chromium version and releasing our stable on the same day as Chrome stable. You can reference Chromium's release schedule [here](https://chromiumdash.appspot.com/schedule). See [Electron's new release cadence blog post](https://www.electronjs.org/blog/12-week-cadence) for more details on our release schedule.
|
||||
* Starting in Electron 16.0, we will release on an 8-week cadence. See [Electron's new 8-week cadence blog post](https://www.electronjs.org/blog/8-week-cadence) for more details.
|
||||
|
||||
**Historical changes:**
|
||||
|
||||
* Since Electron 5, Electron has been publicizing its release dates ([see blog post](https://electronjs.org/blog/electron-5-0-timeline)).
|
||||
* Since Electron 6, Electron major versions have been targeting every other Chromium major version. Each Electron stable should happen on the same day as Chrome stable ([see blog post](https://www.electronjs.org/blog/12-week-cadence)).
|
||||
* Since Electron 16, Electron has been releasing major versions on an 8-week cadence in accordance to Chrome's change to a 4-week release cadence ([see blog post](https://www.electronjs.org/blog/8-week-cadence)).
|
||||
|
||||
:::info Chrome release dates
|
||||
|
||||
Chromium has the own public release schedule [here](https://chromiumdash.appspot.com/schedule).
|
||||
|
||||
:::
|
||||
|
||||
## Version support policy
|
||||
|
||||
:::info
|
||||
|
||||
Beginning in September 2021 (Electron 15), the Electron team
|
||||
will temporarily support the latest **four** stable major versions. This
|
||||
extended support is intended to help Electron developers transition to
|
||||
the [new 8-week release cadence](https://electronjs.org/blog/8-week-cadence),
|
||||
and will continue until the release of Electron 19. At that time,
|
||||
the Electron team will drop support back to the latest three stable major versions.
|
||||
|
||||
:::
|
||||
|
||||
The latest three *stable* major versions are supported by the Electron team.
|
||||
For example, if the latest release is 6.1.x, then the 5.0.x as well
|
||||
as the 4.2.x series are supported. We only support the latest minor release
|
||||
for each stable release series. This means that in the case of a security fix,
|
||||
6.1.x will receive the fix, but we will not release a new version of 6.0.x.
|
||||
|
||||
The latest stable release unilaterally receives all fixes from `main`,
|
||||
and the version prior to that receives the vast majority of those fixes
|
||||
as time and bandwidth warrants. The oldest supported release line will receive
|
||||
only security fixes directly.
|
||||
|
||||
### Breaking API changes
|
||||
|
||||
When an API is changed or removed in a way that breaks existing functionality, the
|
||||
previous functionality will be supported for a minimum of two major versions when
|
||||
possible before being removed. For example, if a function takes three arguments,
|
||||
and that number is reduced to two in major version 10, the three-argument version would
|
||||
continue to work until, at minimum, major version 12. Past the minimum two-version
|
||||
threshold, we will attempt to support backwards compatibility beyond two versions
|
||||
until the maintainers feel the maintenance burden is too high to continue doing so.
|
||||
|
||||
### End-of-life
|
||||
|
||||
When a release branch reaches the end of its support cycle, the series
|
||||
will be deprecated in NPM and a final end-of-support release will be
|
||||
made. This release will add a warning to inform that an unsupported
|
||||
version of Electron is in use.
|
||||
|
||||
These steps are to help app developers learn when a branch they're
|
||||
using becomes unsupported, but without being excessively intrusive
|
||||
to end users.
|
||||
|
||||
If an application has exceptional circumstances and needs to stay
|
||||
on an unsupported series of Electron, developers can silence the
|
||||
end-of-support warning by omitting the final release from the app's
|
||||
`package.json` `devDependencies`. For example, since the 1-6-x series
|
||||
ended with an end-of-support 1.6.18 release, developers could choose
|
||||
to stay in the 1-6-x series without warnings with `devDependency` of
|
||||
`"electron": 1.6.0 - 1.6.17`.
|
||||
| Electron | Alpha | Beta | Stable | Chrome | Node |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- |
|
||||
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | M61 | v8.9 |
|
||||
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | M66 | v10.2 |
|
||||
| 4.0.0 | -- | 2018-Oct-11 | 2018-Dec-20 | M69 | v10.11 |
|
||||
| 5.0.0 | -- | 2019-Jan-22 | 2019-Apr-24 | M73 | v12.0 |
|
||||
| 6.0.0 | -- | 2019-May-01 | 2019-Jul-30 | M76 | v12.4 |
|
||||
| 7.0.0 | -- | 2019-Aug-01 | 2019-Oct-22 | M78 | v12.8 |
|
||||
| 8.0.0 | -- | 2019-Oct-24 | 2020-Feb-04 | M80 | v12.13 |
|
||||
| 9.0.0 | -- | 2020-Feb-06 | 2020-May-19 | M83 | v12.14 |
|
||||
| 10.0.0 | -- | 2020-May-21 | 2020-Aug-25 | M85 | v12.16 |
|
||||
| 11.0.0 | -- | 2020-Aug-27 | 2020-Nov-17 | M87 | v12.18 |
|
||||
| 12.0.0 | -- | 2020-Nov-19 | 2021-Mar-02 | M89 | v14.16 |
|
||||
| 13.0.0 | -- | 2021-Mar-04 | 2021-May-25 | M91 | v14.16 |
|
||||
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | M93 | v14.17 |
|
||||
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | M94 | v16.5 |
|
||||
| 16.0.0 | 2021-Sep-23 | 2021-Oct-20 | 2021-Nov-16 | M96 | v16.9 |
|
||||
| 17.0.0 | 2021-Nov-18 | 2022-Jan-06 | 2022-Feb-01 | M98 | v16.13 |
|
||||
| 18.0.0 | 2022-Feb-03 | 2022-Mar-03 | 2022-Mar-29 | M100 | TBD |
|
||||
|
||||
@@ -48,7 +48,7 @@ Stabilization branches are branches that run parallel to `main`, taking in only
|
||||
|
||||
Since Electron 8, stabilization branches are always **major** version lines, and named against the following template `$MAJOR-x-y` e.g. `8-x-y`. Prior to that we used **minor** version lines and named them as `$MAJOR-$MINOR-x` e.g. `2-0-x`.
|
||||
|
||||
We allow for multiple stabilization branches to exist simultaneously, one for each supported version. For more details on which versions are supported, see our [Electron Releases](./electron-timelines.md) doc.
|
||||
We allow for multiple stabilization branches to exist simultaneously, one for each supported version. For more details on which versions are supported, see our [Electron Release Timelines](./electron-timelines.md) doc.
|
||||
|
||||

|
||||
|
||||
@@ -107,15 +107,6 @@ A few examples of how various SemVer ranges will pick up new releases:
|
||||
|
||||

|
||||
|
||||
### Backport request process
|
||||
|
||||
All supported release lines will accept external pull requests to backport
|
||||
fixes previously merged to `main`, though this may be on a case-by-case
|
||||
basis for some older supported lines. All contested decisions around release
|
||||
line backports will be resolved by the
|
||||
[Releases Working Group](https://github.com/electron/governance/tree/main/wg-releases)
|
||||
as an agenda item at their weekly meeting the week the backport PR is raised.
|
||||
|
||||
## Feature flags
|
||||
|
||||
Feature flags are a common practice in Chromium, and are well-established in the web-development ecosystem. In the context of Electron, a feature flag or **soft branch** must have the following properties:
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
title: 'Examples Overview'
|
||||
description: 'A set of examples for common Electron features'
|
||||
slug: examples
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
# Examples Overview
|
||||
|
||||
In this section, we have collected a set of guides for common features
|
||||
that you may want to implement in your Electron application. Each guide
|
||||
contains a practical example in a minimal, self-contained example app.
|
||||
The easiest way to run these examples is by downloading [Electron Fiddle][fiddle].
|
||||
|
||||
Once Fiddle is installed, you can press on the "Open in Fiddle" button that you
|
||||
will find below code samples like the following one:
|
||||
|
||||
```fiddle docs/fiddles/quick-start
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const replaceText = (selector, text) => {
|
||||
const element = document.getElementById(selector)
|
||||
if (element) element.innerText = text
|
||||
}
|
||||
|
||||
for (const type of ['chrome', 'node', 'electron']) {
|
||||
replaceText(`${type}-version`, process.versions[type])
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
If there is still something that you do not know how to do, please take a look at the [API][app]
|
||||
as there is a chance it might be documented just there (and also open an issue requesting the
|
||||
guide!).
|
||||
|
||||
<!-- guide-table-start -->
|
||||
|
||||
| Guide | Description |
|
||||
| :-------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Message ports] | This guide provides some examples of how you might use MessagePorts in your app to communicate different processes. |
|
||||
| [Device access] | Learn how to access the device hardware (Bluetooth, USB, Serial). |
|
||||
| [Keyboard shortcuts] | Configure local and global keyboard shortcuts for your Electron application. |
|
||||
| [Multithreading] | With Web Workers, it is possible to run JavaScript in OS-level threads |
|
||||
| [Offscreen rendering] | Offscreen rendering lets you obtain the content of a BrowserWindow in a bitmap, so it can be rendered anywhere. |
|
||||
| [Spellchecker] | Learn how to use the built-in spellchecker, set languages, etc. |
|
||||
| [Web embeds] | Discover the different ways to embed third-party web content in your application. |
|
||||
|
||||
<!-- guide-table-end -->
|
||||
|
||||
## How to...?
|
||||
|
||||
You can find the full list of "How to?" in the sidebar. If there is
|
||||
something that you would like to do that is not documented, please join
|
||||
our [Discord server][] and let us know!
|
||||
|
||||
[discord server]: https://discord.com/invite/electron
|
||||
[fiddle]: https://www.electronjs.org/fiddle
|
||||
@@ -1,36 +0,0 @@
|
||||
# Distributing Apps With Electron Forge
|
||||
|
||||
Electron Forge is a tool for packaging and publishing Electron applications.
|
||||
It unifies Electron's build tooling ecosystem into
|
||||
a single extensible interface so that anyone can jump right into making Electron apps.
|
||||
|
||||
## Getting started
|
||||
|
||||
The [Electron Forge docs] contain detailed information on taking your application
|
||||
from source code to your end users' machines.
|
||||
This includes:
|
||||
|
||||
* Packaging your application [(package)]
|
||||
* Generating executables and installers for each OS [(make)], and,
|
||||
* Publishing these files to online platforms to download [(publish)].
|
||||
|
||||
For beginners, we recommend following through Electron's [tutorial] to develop, build,
|
||||
package and publish your first Electron app. If you have already developed an app on your machine
|
||||
and want to start on packaging and distribution, start from [step 5] of the tutorial.
|
||||
|
||||
## Getting help
|
||||
|
||||
* If you need help with developing your app, our [community Discord server][discord] is a great place
|
||||
to get advice from other Electron app developers.
|
||||
* If you suspect you're running into a bug with Forge, please check the [GitHub issue tracker]
|
||||
to see if any existing issues match your problem. If not, feel free to fill out our bug report
|
||||
template and submit a new issue.
|
||||
|
||||
[Electron Forge Docs]: https://www.electronforge.io/
|
||||
[step 5]: ./tutorial-5-packaging.md
|
||||
[(package)]: https://www.electronforge.io/cli#package
|
||||
[(make)]: https://www.electronforge.io/cli#make
|
||||
[(publish)]: https://www.electronforge.io/cli#publish
|
||||
[GitHub issue tracker]: https://github.com/electron-userland/electron-forge/issues
|
||||
[discord]: https://discord.gg/APGC3k5yaH
|
||||
[tutorial]: https://www.electronjs.org/docs/latest/tutorial/tutorial-prerequisites
|
||||
@@ -8,59 +8,6 @@ For a subset of Electron functionality it makes sense to disable certain feature
|
||||
|
||||
Fuses are the solution to this problem, at a high level they are "magic bits" in the Electron binary that can be flipped when packaging your Electron app to enable / disable certain features / restrictions. Because they are flipped at package time before you code sign your app the OS becomes responsible for ensuring those bits aren't flipped back via OS level code signing validation (Gatekeeper / App Locker).
|
||||
|
||||
## Current Fuses
|
||||
|
||||
### `runAsNode`
|
||||
|
||||
**Default:** Enabled
|
||||
**@electron/fuses:** `FuseV1Options.RunAsNode`
|
||||
|
||||
The runAsNode fuse toggles whether the `ELECTRON_RUN_AS_NODE` environment variable is respected or not. Please note that if this fuse is disabled then `process.fork` in the main process will not function as expected as it depends on this environment variable to function.
|
||||
|
||||
### `cookieEncryption`
|
||||
|
||||
**Default:** Disabled
|
||||
**@electron/fuses:** `FuseV1Options.EnableCookieEncryption`
|
||||
|
||||
The cookieEncryption fuse toggles whether the cookie store on disk is encrypted using OS level cryptography keys. By default the sqlite database that Chromium uses to store cookies stores the values in plaintext. If you wish to ensure your apps cookies are encrypted in the same way Chrome does then you should enable this fuse. Please note it is a one-way transition, if you enable this fuse existing unencrypted cookies will be encrypted-on-write but if you then disable the fuse again your cookie store will effectively be corrupt and useless. Most apps can safely enable this fuse.
|
||||
|
||||
### `nodeOptions`
|
||||
|
||||
**Default:** Enabled
|
||||
**@electron/fuses:** `FuseV1Options.EnableNodeOptionsEnvironmentVariable`
|
||||
|
||||
The nodeOptions fuse toggles whether the [`NODE_OPTIONS`](https://nodejs.org/api/cli.html#node_optionsoptions) environment variable is respected or not. This environment variable can be used to pass all kinds of custom options to the Node.js runtime and isn't typically used by apps in production. Most apps can safely disable this fuse.
|
||||
|
||||
### `nodeCliInspect`
|
||||
|
||||
**Default:** Enabled
|
||||
**@electron/fuses:** `FuseV1Options.EnableNodeCliInspectArguments`
|
||||
|
||||
The nodeCliInspect fuse toggles whether the `--inspect`, `--inspect-brk`, etc. flags are respected or not. When disabled it also ensures that `SIGUSR1` signal does not initialize the main process inspector. Most apps can safely disable this fuse.
|
||||
|
||||
### `embeddedAsarIntegrityValidation`
|
||||
|
||||
**Default:** Disabled
|
||||
**@electron/fuses:** `FuseV1Options.EnableEmbeddedAsarIntegrityValidation`
|
||||
|
||||
The embeddedAsarIntegrityValidation fuse toggles an experimental feature on macOS that validates the content of the `app.asar` file when it is loaded. This feature is designed to have a minimal performance impact but may marginally slow down file reads from inside the `app.asar` archive.
|
||||
|
||||
For more information on how to use asar integrity validation please read the [Asar Integrity](asar-integrity.md) documentation.
|
||||
|
||||
### `onlyLoadAppFromAsar`
|
||||
|
||||
**Default:** Disabled
|
||||
**@electron/fuses:** `FuseV1Options.OnlyLoadAppFromAsar`
|
||||
|
||||
The onlyLoadAppFromAsar fuse changes the search system that Electron uses to locate your app code. By default Electron will search in the following order `app.asar` -> `app` -> `default_app.asar`. When this fuse is enabled the search order becomes a single entry `app.asar` thus ensuring that when combined with the `embeddedAsarIntegrityValidation` fuse it is impossible to load non-validated code.
|
||||
|
||||
### `loadBrowserProcessSpecificV8Snapshot`
|
||||
|
||||
**Default:** Disabled
|
||||
**@electron/fuses:** `FuseV1Options.LoadBrowserProcessSpecificV8Snapshot`
|
||||
|
||||
The loadBrowserProcessSpecificV8Snapshot fuse changes which V8 snapshot file is used for the browser process. By default Electron's processes will all use the same V8 snapshot file. When this fuse is enabled the browser process uses the file called `browser_v8_context_snapshot.bin` for its V8 snapshot. The other processes will use the V8 snapshot file that they normally do.
|
||||
|
||||
## How do I flip the fuses?
|
||||
|
||||
### The easy way
|
||||
@@ -73,18 +20,11 @@ require('@electron/fuses').flipFuses(
|
||||
require('electron'),
|
||||
// Fuses to flip
|
||||
{
|
||||
version: FuseVersion.V1,
|
||||
[FuseV1Options.RunAsNode]: false
|
||||
runAsNode: false
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
You can validate the fuses have been flipped or check the fuse status of an arbitrary Electron app using the fuses CLI.
|
||||
|
||||
```bash
|
||||
npx @electron/fuses read --app /Applications/Foo.app
|
||||
```
|
||||
|
||||
### The hard way
|
||||
|
||||
#### Quick Glossary
|
||||
|
||||
@@ -116,7 +116,7 @@ inAppPurchase.getProducts(PRODUCT_IDS).then(products => {
|
||||
console.log(`The price of ${product.localizedTitle} is ${product.formattedPrice}.`)
|
||||
})
|
||||
|
||||
// Ask the user which product they want to purchase.
|
||||
// Ask the user which product he/she wants to purchase.
|
||||
const selectedProduct = products[0]
|
||||
const selectedQuantity = 1
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
title: 'Introduction'
|
||||
description: 'Welcome to the Electron documentation! If this is your first time developing an Electron app, read through this Getting Started section to get familiar with the basics. Otherwise, feel free to explore our guides and API documentation!'
|
||||
slug: /latest/
|
||||
hide_title: false
|
||||
---
|
||||
# Introduction
|
||||
|
||||
# What is Electron?
|
||||
Welcome to the Electron documentation! If this is your first time developing
|
||||
an Electron app, read through this Getting Started section to get familiar with the
|
||||
basics. Otherwise, feel free to explore our guides and API documentation!
|
||||
|
||||
## What is Electron?
|
||||
|
||||
Electron is a framework for building desktop applications using JavaScript,
|
||||
HTML, and CSS. By embedding [Chromium][chromium] and [Node.js][node] into its
|
||||
@@ -13,12 +12,20 @@ binary, Electron allows you to maintain one JavaScript codebase and create
|
||||
cross-platform apps that work on Windows, macOS, and Linux — no native development
|
||||
experience required.
|
||||
|
||||
## Getting started
|
||||
## Prerequisites
|
||||
|
||||
We recommend you to start with the [tutorial], which guides you through the
|
||||
process of developing an Electron app and distributing it to users.
|
||||
The [examples] and [API documentation] are also good places to browse around
|
||||
and discover new things.
|
||||
These docs operate under the assumption that the reader is familiar with both
|
||||
Node.js and general web development. If you need to get more comfortable with
|
||||
either of these areas, we recommend the following resources:
|
||||
|
||||
* [Getting started with the Web (MDN)][mdn-guide]
|
||||
* [Introduction to Node.js][node-guide]
|
||||
|
||||
Moreover, you'll have a better time understanding how Electron works if you get
|
||||
acquainted with Chromium's process model. You can get a brief overview of
|
||||
Chrome architecture with the [Chrome comic][comic], which was released alongside
|
||||
Chrome's launch back in 2008. Although it's been over a decade since then, the
|
||||
core principles introduced in the comic remain helpful to understand Electron.
|
||||
|
||||
## Running examples with Electron Fiddle
|
||||
|
||||
@@ -32,45 +39,21 @@ a code block. If you have Fiddle installed, this button will open a
|
||||
`fiddle.electronjs.org` link that will automatically load the example into Fiddle,
|
||||
no copy-pasting required.
|
||||
|
||||
```fiddle docs/fiddles/quick-start
|
||||
```
|
||||
|
||||
## What is in the docs?
|
||||
|
||||
All the official documentation is available from the sidebar. These
|
||||
are the different categories and what you can expect on each one:
|
||||
|
||||
- **Tutorial**: An end-to-end guide on how to create and publish your first Electron
|
||||
application.
|
||||
- **Processes in Electron**: In-depth reference on Electron processes and how to work with them.
|
||||
- **Best Practices**: Important checklists to keep in mind when developing an Electron app.
|
||||
- **Examples**: Quick references to add features to your Electron app.
|
||||
- **Development**: Miscellaneous development guides.
|
||||
- **Distribution**: Learn how to distribute your app to end users.
|
||||
- **Testing And Debugging**: How to debug JavaScript, write tests, and other tools used
|
||||
to create quality Electron applications.
|
||||
- **References**: Useful links to better understand how the Electron project works
|
||||
and is organized.
|
||||
- **Contributing**: Compiling Electron and making contributions can be daunting.
|
||||
We try to make it easier in this section.
|
||||
|
||||
## Getting help
|
||||
|
||||
Are you getting stuck anywhere? Here are a few links to places to look:
|
||||
|
||||
- If you need help with developing your app, our [community Discord server][discord]
|
||||
is a great place to get advice from other Electron app developers.
|
||||
- If you suspect you're running into a bug with the `electron` package, please check
|
||||
the [GitHub issue tracker][issue-tracker] to see if any existing issues match your
|
||||
problem. If not, feel free to fill out our bug report template and submit a new issue.
|
||||
* If you need help with developing your app, our [community Discord server][discord]
|
||||
is a great place to get advice from other Electron app developers.
|
||||
* If you suspect you're running into a bug with the `electron` package, please check
|
||||
the [GitHub issue tracker][issue-tracker] to see if any existing issues match your
|
||||
problem. If not, feel free to fill out our bug report template and submit a new issue.
|
||||
|
||||
<!-- Links -->
|
||||
|
||||
[tutorial]: tutorial-1-prerequisites.md
|
||||
[api documentation]: ../api/app.md
|
||||
[chromium]: https://www.chromium.org/
|
||||
[discord]: https://discord.com/invite/APGC3k5yaH
|
||||
[examples]: examples.md
|
||||
[node]: https://nodejs.org/
|
||||
[mdn-guide]: https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web
|
||||
[node-guide]: https://nodejs.dev/learn
|
||||
[comic]: https://www.google.com/googlebooks/chrome/
|
||||
[fiddle]: https://electronjs.org/fiddle
|
||||
[issue-tracker]: https://github.com/electron/electron/issues
|
||||
[node]: https://nodejs.org/
|
||||
[discord]: https://discord.gg/electronjs
|
||||
|
||||
@@ -232,7 +232,7 @@ how to meet the Mac App Store requirements.
|
||||
|
||||
### Upload
|
||||
|
||||
[Apple Transporter][apple-transporter] should be used to upload the signed app to App Store
|
||||
The Application Loader should be used to upload the signed app to iTunes
|
||||
Connect for processing, making sure you have [created a record][create-record]
|
||||
before uploading.
|
||||
|
||||
@@ -345,8 +345,7 @@ Electron uses following cryptographic algorithms:
|
||||
[app-sandboxing]: https://developer.apple.com/app-sandboxing/
|
||||
[app-notarization]: https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution
|
||||
[submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html
|
||||
[create-record]: https://help.apple.com/app-store-connect/#/dev2cd126805
|
||||
[apple-transporter]: https://help.apple.com/itc/transporteruserguide/en.lproj/static.html
|
||||
[create-record]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/CreatingiTunesConnectRecord.html
|
||||
[submit-for-review]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/SubmittingTheApp.html
|
||||
[export-compliance]: https://help.apple.com/app-store-connect/#/devc3f64248f
|
||||
[user-selected]: https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW6
|
||||
|
||||
@@ -8,7 +8,8 @@ your app.
|
||||
|
||||
Here is a very brief example of what a MessagePort is and how it works:
|
||||
|
||||
```js title='renderer.js (Renderer Process)'
|
||||
```js
|
||||
// renderer.js ///////////////////////////////////////////////////////////////
|
||||
// MessagePorts are created in pairs. A connected pair of message ports is
|
||||
// called a channel.
|
||||
const channel = new MessageChannel()
|
||||
@@ -27,7 +28,8 @@ port2.postMessage({ answer: 42 })
|
||||
ipcRenderer.postMessage('port', null, [port1])
|
||||
```
|
||||
|
||||
```js title='main.js (Main Process)'
|
||||
```js
|
||||
// main.js ///////////////////////////////////////////////////////////////////
|
||||
// In the main process, we receive the port.
|
||||
ipcMain.on('port', (event) => {
|
||||
// When we receive a MessagePort in the main process, it becomes a
|
||||
@@ -82,84 +84,14 @@ process, you can listen for the `close` event by calling `port.on('close',
|
||||
|
||||
## Example use cases
|
||||
|
||||
### Setting up a MessageChannel between two renderers
|
||||
|
||||
In this example, the main process sets up a MessageChannel, then sends each port
|
||||
to a different renderer. This allows renderers to send messages to each other
|
||||
without needing to use the main process as an in-between.
|
||||
|
||||
```js title='main.js (Main Process)'
|
||||
const { BrowserWindow, app, MessageChannelMain } = require('electron')
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
// create the windows.
|
||||
const mainWindow = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
contextIsolation: false,
|
||||
preload: 'preloadMain.js'
|
||||
}
|
||||
})
|
||||
|
||||
const secondaryWindow = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
contextIsolation: false,
|
||||
preload: 'preloadSecondary.js'
|
||||
}
|
||||
})
|
||||
|
||||
// set up the channel.
|
||||
const { port1, port2 } = new MessageChannelMain()
|
||||
|
||||
// once the webContents are ready, send a port to each webContents with postMessage.
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
mainWindow.webContents.postMessage('port', null, [port1])
|
||||
})
|
||||
|
||||
secondaryWindow.once('ready-to-show', () => {
|
||||
secondaryWindow.webContents.postMessage('port', null, [port2])
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
Then, in your preload scripts you receive the port through IPC and set up the
|
||||
listeners.
|
||||
|
||||
```js title='preloadMain.js and preloadSecondary.js (Preload scripts)'
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
ipcRenderer.on('port', e => {
|
||||
// port received, make it globally available.
|
||||
window.electronMessagePort = e.ports[0]
|
||||
|
||||
window.electronMessagePort.onmessage = messageEvent => {
|
||||
// handle message
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
In this example messagePort is bound to the `window` object directly. It is better
|
||||
to use `contextIsolation` and set up specific contextBridge calls for each of your
|
||||
expected messages, but for the simplicity of this example we don't. You can find an
|
||||
example of context isolation further down this page at [Communicating directly between the main process and the main world of a context-isolated page](#communicating-directly-between-the-main-process-and-the-main-world-of-a-context-isolated-page)
|
||||
|
||||
That means window.electronMessagePort is globally available and you can call
|
||||
`postMessage` on it from anywhere in your app to send a message to the other
|
||||
renderer.
|
||||
|
||||
```js title='renderer.js (Renderer Process)'
|
||||
// elsewhere in your code to send a message to the other renderers message handler
|
||||
window.electronMessagePort.postmessage('ping')
|
||||
```
|
||||
|
||||
### Worker process
|
||||
|
||||
In this example, your app has a worker process implemented as a hidden window.
|
||||
You want the app page to be able to communicate directly with the worker
|
||||
process, without the performance overhead of relaying via the main process.
|
||||
|
||||
```js title='main.js (Main Process)'
|
||||
```js
|
||||
// main.js ///////////////////////////////////////////////////////////////////
|
||||
const { BrowserWindow, app, ipcMain, MessageChannelMain } = require('electron')
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
@@ -197,7 +129,8 @@ app.whenReady().then(async () => {
|
||||
})
|
||||
```
|
||||
|
||||
```html title='worker.html'
|
||||
```html
|
||||
<!-- worker.html ------------------------------------------------------------>
|
||||
<script>
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
@@ -220,7 +153,8 @@ ipcRenderer.on('new-client', (event) => {
|
||||
</script>
|
||||
```
|
||||
|
||||
```html title='app.html'
|
||||
```html
|
||||
<!-- app.html --------------------------------------------------------------->
|
||||
<script>
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
@@ -248,7 +182,9 @@ Electron's built-in IPC methods only support two modes: fire-and-forget
|
||||
can implement a "response stream", where a single request responds with a
|
||||
stream of data.
|
||||
|
||||
```js title='renderer.js (Renderer Process)'
|
||||
```js
|
||||
// renderer.js ///////////////////////////////////////////////////////////////
|
||||
|
||||
const makeStreamingRequest = (element, callback) => {
|
||||
// MessageChannels are lightweight--it's cheap to create a new one for each
|
||||
// request.
|
||||
@@ -272,12 +208,14 @@ const makeStreamingRequest = (element, callback) => {
|
||||
}
|
||||
|
||||
makeStreamingRequest(42, (data) => {
|
||||
console.log('got response data:', data)
|
||||
console.log('got response data:', event.data)
|
||||
})
|
||||
// We will see "got response data: 42" 10 times.
|
||||
```
|
||||
|
||||
```js title='main.js (Main Process)'
|
||||
```js
|
||||
// main.js ///////////////////////////////////////////////////////////////////
|
||||
|
||||
ipcMain.on('give-me-a-stream', (event, msg) => {
|
||||
// The renderer has sent us a MessagePort that it wants us to send our
|
||||
// response over.
|
||||
@@ -304,7 +242,8 @@ the renderer are delivered to the isolated world, rather than to the main
|
||||
world. Sometimes you want to deliver messages to the main world directly,
|
||||
without having to step through the isolated world.
|
||||
|
||||
```js title='main.js (Main Process)'
|
||||
```js
|
||||
// main.js ///////////////////////////////////////////////////////////////////
|
||||
const { BrowserWindow, app, MessageChannelMain } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
@@ -339,7 +278,8 @@ app.whenReady().then(async () => {
|
||||
})
|
||||
```
|
||||
|
||||
```js title='preload.js (Preload Script)'
|
||||
```js
|
||||
// preload.js ////////////////////////////////////////////////////////////////
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
// We need to wait until the main world is ready to receive the message before
|
||||
@@ -357,7 +297,8 @@ ipcRenderer.on('main-world-port', async (event) => {
|
||||
})
|
||||
```
|
||||
|
||||
```html title='index.html'
|
||||
```html
|
||||
<!-- index.html ------------------------------------------------------------->
|
||||
<script>
|
||||
window.onmessage = (event) => {
|
||||
// event.source === window means the message is coming from the preload
|
||||
|
||||