mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
55 Commits
v21.0.0-al
...
v20.0.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e774d4f348 | ||
|
|
3e18fba853 | ||
|
|
fa1382d980 | ||
|
|
8f738edc40 | ||
|
|
5b4577af20 | ||
|
|
cf38b9e375 | ||
|
|
bbc84b0e9a | ||
|
|
c655ed075a | ||
|
|
c48e0b8ab6 | ||
|
|
46d609fc2c | ||
|
|
03fe3c42d4 | ||
|
|
952e2905b9 | ||
|
|
7619dd51bf | ||
|
|
e2b823fb07 | ||
|
|
a1dcdc4664 | ||
|
|
2b2900a2f1 | ||
|
|
d87bad743c | ||
|
|
33670ac928 | ||
|
|
8ecbc11aa2 | ||
|
|
4ab3b1d624 | ||
|
|
bce95c4886 | ||
|
|
5b583c8808 | ||
|
|
c20d6e54c5 | ||
|
|
ff7f2a5091 | ||
|
|
10062c9a5b | ||
|
|
82a6e9bd5a | ||
|
|
10131e36f3 | ||
|
|
37078297c6 | ||
|
|
48f4ef65ed | ||
|
|
e174aac845 | ||
|
|
dd1a692aba | ||
|
|
aa05c43994 | ||
|
|
16561d08ae | ||
|
|
edc0a47c89 | ||
|
|
018e2aee8d | ||
|
|
dd10a5ebf2 | ||
|
|
2fe7d59437 | ||
|
|
a4a9210d2d | ||
|
|
69179bbfe7 | ||
|
|
b64b87a8d6 | ||
|
|
7bdc9d8039 | ||
|
|
cbe2a458c9 | ||
|
|
d20e547316 | ||
|
|
bde27c7e6b | ||
|
|
d0d5e20efb | ||
|
|
dc452de295 | ||
|
|
ade2b02e1c | ||
|
|
73e3c29c94 | ||
|
|
24df260185 | ||
|
|
4fe31bd1aa | ||
|
|
948949f83d | ||
|
|
bba63609f2 | ||
|
|
4b793692ea | ||
|
|
f3da81cb77 | ||
|
|
6f8bf917f7 |
@@ -53,8 +53,14 @@ executors:
|
||||
description: "macOS executor size"
|
||||
type: enum
|
||||
enum: ["macos.x86.medium.gen2", "large"]
|
||||
xcode:
|
||||
description: "xcode version"
|
||||
default: 13.3.0
|
||||
type: enum
|
||||
enum: ["12.4.0", "13.3.0"]
|
||||
|
||||
macos:
|
||||
xcode: 13.3.0
|
||||
xcode: << parameters.xcode >>
|
||||
resource_class: << parameters.size >>
|
||||
|
||||
# Electron Runners
|
||||
@@ -119,9 +125,6 @@ env-apple-silicon: &env-apple-silicon
|
||||
USE_PREBUILT_V8_CONTEXT_SNAPSHOT: 1
|
||||
npm_config_arch: arm64
|
||||
|
||||
env-runner: &env-runner
|
||||
IS_ELECTRON_RUNNER: 1
|
||||
|
||||
env-arm64: &env-arm64
|
||||
GN_EXTRA_ARGS: 'target_cpu = "arm64" fatal_linker_warnings = false enable_linux_installer = false'
|
||||
MKSNAPSHOT_TOOLCHAIN: //build/toolchain/linux:clang_arm64
|
||||
@@ -346,7 +349,7 @@ step-wait-for-goma: &step-wait-for-goma
|
||||
sleep 5
|
||||
done
|
||||
echo "Goma ready"
|
||||
no_output_timeout: 5m
|
||||
no_output_timeout: 2m
|
||||
|
||||
step-restore-brew-cache: &step-restore-brew-cache
|
||||
restore_cache:
|
||||
@@ -508,7 +511,6 @@ step-install-signing-cert-on-mac: &step-install-signing-cert-on-mac
|
||||
name: Import and trust self-signed codesigning cert on MacOS
|
||||
command: |
|
||||
if [ "$TARGET_ARCH" != "arm64" ] && [ "`uname`" == "Darwin" ]; then
|
||||
sudo security authorizationdb write com.apple.trust-settings.admin allow
|
||||
cd src/electron
|
||||
./script/codesign/generate-identity.sh
|
||||
fi
|
||||
@@ -637,7 +639,7 @@ step-electron-publish: &step-electron-publish
|
||||
echo 'Uploading Electron release distribution to Azure'
|
||||
script/release/uploaders/upload.py --verbose --UPLOAD_TO_STORAGE
|
||||
else
|
||||
echo 'Uploading Electron release distribution to GitHub releases'
|
||||
echo 'Uploading Electron release distribution to Github releases'
|
||||
script/release/uploaders/upload.py --verbose
|
||||
fi
|
||||
|
||||
@@ -1006,17 +1008,9 @@ steps-electron-gn-check: &steps-electron-gn-check
|
||||
- *step-generate-deps-hash
|
||||
- *step-touch-sync-done
|
||||
- maybe-restore-portaled-src-cache
|
||||
- run:
|
||||
name: Ensure src checkout worked
|
||||
command: |
|
||||
if [ ! -d "src/third_party/blink" ]; then
|
||||
echo src cache was not restored for an unknown reason
|
||||
exit 1
|
||||
fi
|
||||
- run:
|
||||
name: Wipe Electron
|
||||
command: rm -rf src/electron
|
||||
- *step-checkout-electron
|
||||
- *step-wait-for-goma
|
||||
- *step-gn-gen-default
|
||||
- *step-gn-check
|
||||
|
||||
steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-change
|
||||
steps:
|
||||
@@ -1038,7 +1032,6 @@ steps-tests: &steps-tests
|
||||
- *step-setup-linux-for-headless-testing
|
||||
- *step-restore-brew-cache
|
||||
- *step-fix-known-hosts-linux
|
||||
- install-python2-mac
|
||||
- *step-install-signing-cert-on-mac
|
||||
|
||||
- run:
|
||||
@@ -1137,7 +1130,7 @@ commands:
|
||||
- run:
|
||||
name: Install python2 on macos
|
||||
command: |
|
||||
if [ "`uname`" == "Darwin" ] && [ "$IS_ELECTRON_RUNNER" != "1" ]; then
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
if [ ! -f "python-downloads/python-2.7.18-macosx10.9.pkg" ]; then
|
||||
mkdir python-downloads
|
||||
echo 'Downloading Python 2.7.18'
|
||||
@@ -2051,6 +2044,7 @@ jobs:
|
||||
osx-testing-x64-tests:
|
||||
executor:
|
||||
name: macos
|
||||
xcode: 12.4.0
|
||||
size: macos.x86.medium.gen2
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
@@ -2064,12 +2058,12 @@ jobs:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
<<: *env-apple-silicon
|
||||
<<: *env-runner
|
||||
<<: *steps-tests
|
||||
|
||||
mas-testing-x64-tests:
|
||||
executor:
|
||||
name: macos
|
||||
xcode: 12.4.0
|
||||
size: macos.x86.medium.gen2
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
@@ -2083,7 +2077,6 @@ jobs:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
<<: *env-apple-silicon
|
||||
<<: *env-runner
|
||||
<<: *steps-tests
|
||||
|
||||
# List all workflows
|
||||
|
||||
178
.github/workflows/electron_woa_testing.yml
vendored
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 }}"}
|
||||
@@ -1,31 +0,0 @@
|
||||
name: Trigger Major Release Dependency Updates
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
jobs:
|
||||
check_tag:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check Tag
|
||||
run: |
|
||||
if [[ ${{ github.event.ref }} =~ ^refs/tags/v[0-9]+\.0\.0$ ]]; then
|
||||
echo ::set-output name=should_release::true
|
||||
fi
|
||||
trigger:
|
||||
runs-on: ubuntu-latest
|
||||
needs: check_tag
|
||||
if: jobs.check_tag.outputs.should_release == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Trigger New chromedriver Release
|
||||
run: |
|
||||
gh api /repos/:owner/chromedriver/actions/workflows/release.yml/dispatches --input - <<< '{"ref":"main","inputs":{"version":"${{ github.event.release.tag_name }}"}}'
|
||||
- name: Trigger New mksnapshot Release
|
||||
run: |
|
||||
gh api /repos/:owner/mksnapshot/actions/workflows/release.yml/dispatches --input - <<< '{"ref":"main","inputs":{"version":"${{ github.event.release.tag_name }}"}}'
|
||||
1
.husky/.gitignore
vendored
Normal file
1
.husky/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
_
|
||||
@@ -23,5 +23,7 @@
|
||||
"br_spaces": 0
|
||||
},
|
||||
"single-h1": false,
|
||||
"no-inline-html": false
|
||||
"no-inline-html": {
|
||||
"allowed_elements": ["br"]
|
||||
}
|
||||
}
|
||||
|
||||
16
BUILD.gn
16
BUILD.gn
@@ -135,7 +135,7 @@ config("electron_lib_config") {
|
||||
include_dirs = [ "." ]
|
||||
}
|
||||
|
||||
# We generate the definitions twice here, once in //electron/electron.d.ts
|
||||
# We geneate the definitions twice here, once in //electron/electron.d.ts
|
||||
# and once in $target_gen_dir
|
||||
# The one in $target_gen_dir is used for the actual TSC build later one
|
||||
# and the one in //electron/electron.d.ts is used by your IDE (vscode)
|
||||
@@ -233,7 +233,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 ]
|
||||
}
|
||||
|
||||
@@ -391,7 +390,6 @@ source_set("electron_lib") {
|
||||
"//components/user_prefs",
|
||||
"//components/viz/host",
|
||||
"//components/viz/service",
|
||||
"//components/webrtc",
|
||||
"//content/public/browser",
|
||||
"//content/public/child",
|
||||
"//content/public/gpu",
|
||||
@@ -567,9 +565,8 @@ source_set("electron_lib") {
|
||||
"//ui/base/ime/linux",
|
||||
"//ui/events/devices/x11",
|
||||
"//ui/events/platform/x11",
|
||||
"//ui/linux:linux_ui",
|
||||
"//ui/linux:linux_ui_factory",
|
||||
"//ui/views/controls/webview",
|
||||
"//ui/views/linux_ui:linux_ui_factory",
|
||||
"//ui/wm",
|
||||
]
|
||||
if (ozone_platform_x11) {
|
||||
@@ -674,6 +671,8 @@ source_set("electron_lib") {
|
||||
|
||||
if (enable_basic_printing) {
|
||||
sources += [
|
||||
"shell/browser/printing/print_preview_message_handler.cc",
|
||||
"shell/browser/printing/print_preview_message_handler.h",
|
||||
"shell/browser/printing/print_view_manager_electron.cc",
|
||||
"shell/browser/printing/print_view_manager_electron.h",
|
||||
"shell/renderer/printing/print_render_frame_helper_delegate.cc",
|
||||
@@ -901,13 +900,6 @@ if (is_mac) {
|
||||
"@executable_path/../../../../../..",
|
||||
]
|
||||
}
|
||||
|
||||
# For component ffmpeg under non-component build, it is linked from
|
||||
# @loader_path. However the ffmpeg.dylib is moved to a different place
|
||||
# when generating app bundle, and we should change to link from @rpath.
|
||||
if (is_component_ffmpeg && !is_component_build) {
|
||||
ldflags += [ "-Wcrl,installnametool,-change,@loader_path/libffmpeg.dylib,@rpath/libffmpeg.dylib" ]
|
||||
}
|
||||
}
|
||||
|
||||
template("electron_helper_app") {
|
||||
|
||||
4
DEPS
4
DEPS
@@ -2,9 +2,9 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'105.0.5187.0',
|
||||
'104.0.5073.0',
|
||||
'node_version':
|
||||
'v16.16.0',
|
||||
'v16.15.0',
|
||||
'nan_version':
|
||||
'16fa32231e2ccd89d2804b3f765319128b20c4ac',
|
||||
'squirrel.mac_version':
|
||||
|
||||
@@ -1 +1 @@
|
||||
21.0.0-alpha.3
|
||||
20.0.0-beta.4
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[](https://circleci.com/gh/electron/electron/tree/main)
|
||||
[](https://ci.appveyor.com/project/electron-bot/electron-ljo26/branch/main)
|
||||
[](https://discord.gg/electronjs)
|
||||
[](https://discord.com/invite/APGC3k5yaH)
|
||||
|
||||
:memo: Available Translations: 🇨🇳 🇧🇷 🇪🇸 🇯🇵 🇷🇺 🇫🇷 🇺🇸 🇩🇪.
|
||||
View these docs in other languages at [electron/i18n](https://github.com/electron/i18n/tree/master/content/).
|
||||
|
||||
22
appveyor.yml
22
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.
|
||||
@@ -12,7 +12,7 @@
|
||||
# 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.
|
||||
# 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,
|
||||
@@ -170,16 +170,19 @@ build_script:
|
||||
- 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
|
||||
# Temporarily disable symbol generation on 32-bit Windows due to failures
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
if ($env:GN_CONFIG -eq 'release' -And $env:TARGET_ARCH -ne 'ia32') {
|
||||
# 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
|
||||
if ($env:TARGET_ARCH -ne 'ia32') {
|
||||
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.
|
||||
@@ -201,9 +204,10 @@ test_script:
|
||||
echo "Skipping tests for $env:GN_CONFIG build"
|
||||
}
|
||||
- cd electron
|
||||
- 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 )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running remote test suite & node script/yarn test -- --trace-uncaught --runners=remote --runTestFilesSeparately --enable-logging=file --log-file=%cd%\electron.log )
|
||||
- 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 )
|
||||
# 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"
|
||||
@@ -223,7 +227,7 @@ deploy_script:
|
||||
& python script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
} elseif (Test-Path Env:\TEST_WOA) {
|
||||
node script/release/ci-release-build.js --job=electron-woa-testing --ci=GHA --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH
|
||||
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:
|
||||
# Uncomment this lines to enable RDP
|
||||
|
||||
121
azure-pipelines-arm.yml
Normal file
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
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 = 109
|
||||
node_module_version = 107
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_embedder_string = "-electron.0"
|
||||
@@ -45,3 +45,5 @@ enable_cet_shadow_stack = false
|
||||
# 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
|
||||
|
||||
@@ -1,22 +1,33 @@
|
||||
template("node_action") {
|
||||
assert(defined(invoker.script), "Need script path to run")
|
||||
assert(defined(invoker.args), "Need script arguments")
|
||||
import("node.gni")
|
||||
|
||||
# TODO(MarshallOfSound): Move to electron/node, this is the only place it is used now
|
||||
# Run an action with a given working directory. Behaves identically to the
|
||||
# action() target type, with the exception that it changes directory before
|
||||
# running the script.
|
||||
#
|
||||
# Parameters:
|
||||
# cwd [required]: Directory to change to before running the script.
|
||||
template("chdir_action") {
|
||||
action(target_name) {
|
||||
forward_variables_from(invoker,
|
||||
"*",
|
||||
[
|
||||
"deps",
|
||||
"public_deps",
|
||||
"sources",
|
||||
"inputs",
|
||||
"outputs",
|
||||
"script",
|
||||
"args",
|
||||
])
|
||||
if (!defined(inputs)) {
|
||||
inputs = []
|
||||
assert(defined(cwd), "Need cwd in $target_name")
|
||||
script = "//electron/build/run-in-dir.py"
|
||||
if (defined(sources)) {
|
||||
sources += [ invoker.script ]
|
||||
} else {
|
||||
assert(defined(inputs))
|
||||
inputs += [ invoker.script ]
|
||||
}
|
||||
inputs += [ invoker.script ]
|
||||
script = "//electron/build/run-node.py"
|
||||
args = [ rebase_path(invoker.script) ] + invoker.args
|
||||
args = [
|
||||
rebase_path(cwd),
|
||||
rebase_path(invoker.script),
|
||||
]
|
||||
args += invoker.args
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
config("build_time_executable") {
|
||||
configs = []
|
||||
|
||||
if (is_electron_build && !is_component_build) {
|
||||
# The executables which have this config applied are dependent on ffmpeg,
|
||||
# which is always a shared library in an Electron build. However, in the
|
||||
# non-component build, executables don't have rpath set to search for
|
||||
# libraries in the executable's directory, so ffmpeg cannot be found. So
|
||||
# let's make sure rpath is set here.
|
||||
# See '//build/config/gcc/BUILD.gn' for details on the rpath setting.
|
||||
if (is_linux) {
|
||||
configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
ldflags = [ "-Wl,-rpath,@loader_path/." ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# For MAS build, we force defining "MAS_BUILD".
|
||||
config("mas_build") {
|
||||
if (is_mas_build) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -19,13 +19,17 @@ TEMPLATE_H = """
|
||||
#define FUSE_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace electron::fuses {
|
||||
namespace electron {
|
||||
|
||||
namespace fuses {
|
||||
|
||||
extern const volatile char kFuseWire[];
|
||||
|
||||
{getters}
|
||||
|
||||
} // namespace electron::fuses
|
||||
} // namespace fuses
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_FUSES_H_
|
||||
"""
|
||||
@@ -33,13 +37,17 @@ extern const volatile char kFuseWire[];
|
||||
TEMPLATE_CC = """
|
||||
#include "electron/fuses.h"
|
||||
|
||||
namespace electron::fuses {
|
||||
namespace electron {
|
||||
|
||||
namespace fuses {
|
||||
|
||||
const volatile char kFuseWire[] = { /* sentinel */ {sentinel}, /* fuse_version */ {fuse_version}, /* fuse_wire_length */ {fuse_wire_length}, /* fuse_wire */ {initial_config}};
|
||||
|
||||
{getters}
|
||||
|
||||
} // namespace electron:fuses
|
||||
}
|
||||
|
||||
}
|
||||
"""
|
||||
|
||||
with open(os.path.join(dir_path, "fuses.json5"), 'r') as f:
|
||||
|
||||
@@ -8,7 +8,9 @@ TEMPLATE = """
|
||||
#include "node_native_module.h"
|
||||
#include "node_internals.h"
|
||||
|
||||
namespace node::native_module {{
|
||||
namespace node {{
|
||||
|
||||
namespace native_module {{
|
||||
|
||||
{definitions}
|
||||
|
||||
@@ -16,7 +18,9 @@ void NativeModuleLoader::LoadEmbedderJavaScriptSource() {{
|
||||
{initializers}
|
||||
}}
|
||||
|
||||
}} // namespace node::native_module
|
||||
}} // namespace native_module
|
||||
|
||||
}} // namespace node
|
||||
"""
|
||||
|
||||
def main():
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# Cocoa .app bundle. The presence of these empty directories is sufficient to
|
||||
# convince Cocoa that the application supports the named localization, even if
|
||||
# an InfoPlist.strings file is not provided. Chrome uses these empty locale
|
||||
# directories for its helper executable bundles, which do not otherwise
|
||||
# directoires for its helper executable bundles, which do not otherwise
|
||||
# require any direct Cocoa locale support.
|
||||
|
||||
import os
|
||||
|
||||
21
build/node.gni
Normal file
21
build/node.gni
Normal file
@@ -0,0 +1,21 @@
|
||||
template("node_action") {
|
||||
assert(defined(invoker.script), "Need script path to run")
|
||||
assert(defined(invoker.args), "Need script argumets")
|
||||
|
||||
action(target_name) {
|
||||
forward_variables_from(invoker,
|
||||
[
|
||||
"deps",
|
||||
"public_deps",
|
||||
"sources",
|
||||
"inputs",
|
||||
"outputs",
|
||||
])
|
||||
if (!defined(inputs)) {
|
||||
inputs = []
|
||||
}
|
||||
inputs += [ invoker.script ]
|
||||
script = "//electron/build/run-node.py"
|
||||
args = [ rebase_path(invoker.script) ] + invoker.args
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
template("npm_action") {
|
||||
assert(defined(invoker.script),
|
||||
"Need script name to run (must be defined in package.json)")
|
||||
assert(defined(invoker.args), "Need script arguments")
|
||||
assert(defined(invoker.args), "Need script argumets")
|
||||
|
||||
action("npm_pre_flight_" + target_name) {
|
||||
inputs = [
|
||||
|
||||
@@ -51,7 +51,7 @@ template("compile_ib_files") {
|
||||
# Template to compile and package Mac XIB files as bundle data.
|
||||
# Arguments
|
||||
# sources:
|
||||
# list of string, sources to compile
|
||||
# list of string, sources to comiple
|
||||
# output_path:
|
||||
# (optional) string, the path to use for the outputs list in the
|
||||
# bundle_data step. If unspecified, defaults to bundle_resources_dir.
|
||||
|
||||
@@ -92,7 +92,6 @@ static_library("chrome") {
|
||||
"//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/platform_util_mac.mm",
|
||||
"//chrome/browser/process_singleton_mac.mm",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.h",
|
||||
"//chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.mm",
|
||||
@@ -217,8 +216,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/printing/printer_query.h",
|
||||
"//chrome/browser/printing/printing_service.cc",
|
||||
"//chrome/browser/printing/printing_service.h",
|
||||
"//components/printing/browser/print_to_pdf/pdf_print_utils.cc",
|
||||
"//components/printing/browser/print_to_pdf/pdf_print_utils.h",
|
||||
]
|
||||
|
||||
if (enable_oop_printing) {
|
||||
@@ -388,19 +385,14 @@ source_set("chrome_spellchecker") {
|
||||
"//chrome/browser/spellchecker/spellcheck_factory.h",
|
||||
"//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc",
|
||||
"//chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h",
|
||||
"//chrome/browser/spellchecker/spellcheck_language_blocklist_policy_handler.cc",
|
||||
"//chrome/browser/spellchecker/spellcheck_language_blocklist_policy_handler.h",
|
||||
"//chrome/browser/spellchecker/spellcheck_language_policy_handler.cc",
|
||||
"//chrome/browser/spellchecker/spellcheck_language_policy_handler.h",
|
||||
"//chrome/browser/spellchecker/spellcheck_service.cc",
|
||||
"//chrome/browser/spellchecker/spellcheck_service.h",
|
||||
]
|
||||
|
||||
if (!is_mac) {
|
||||
sources += [
|
||||
"//chrome/browser/spellchecker/spellcheck_language_blocklist_policy_handler.cc",
|
||||
"//chrome/browser/spellchecker/spellcheck_language_blocklist_policy_handler.h",
|
||||
"//chrome/browser/spellchecker/spellcheck_language_policy_handler.cc",
|
||||
"//chrome/browser/spellchecker/spellcheck_language_policy_handler.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (has_spellcheck_panel) {
|
||||
sources += [
|
||||
"//chrome/browser/spellchecker/spell_check_panel_host_impl.cc",
|
||||
|
||||
@@ -69,6 +69,9 @@ an issue:
|
||||
* [Windows Store](tutorial/windows-store-guide.md)
|
||||
* [Snapcraft](tutorial/snapcraft.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
|
||||
|
||||
@@ -130,11 +130,6 @@ set `NSPrincipalClass` to `AtomApplication`.
|
||||
|
||||
You should call `event.preventDefault()` if you want to handle this event.
|
||||
|
||||
As with the `open-file` event, be sure to register a listener for the `open-url`
|
||||
event early in your application startup to detect if the the application being
|
||||
is being opened to handle a URL. If you register the listener in response to a
|
||||
`ready` event, you'll miss URLs that trigger the launch of your application.
|
||||
|
||||
### Event: 'activate' _macOS_
|
||||
|
||||
Returns:
|
||||
@@ -1386,7 +1381,7 @@ method returns false. If we fail to perform the copy, then this method will
|
||||
throw an error. The message in the error should be informative and tell
|
||||
you exactly what went wrong.
|
||||
|
||||
By default, if an app of the same name as the one being moved exists in the Applications directory and is _not_ running, the existing app will be trashed and the active app moved into its place. If it _is_ running, the preexisting running app will assume focus and the previously active app will quit itself. This behavior can be changed by providing the optional conflict handler, where the boolean returned by the handler determines whether or not the move conflict is resolved with default behavior. i.e. returning `false` will ensure no further action is taken, returning `true` will result in the default behavior and the method continuing.
|
||||
By default, if an app of the same name as the one being moved exists in the Applications directory and is _not_ running, the existing app will be trashed and the active app moved into its place. If it _is_ running, the pre-existing running app will assume focus and the previously active app will quit itself. This behavior can be changed by providing the optional conflict handler, where the boolean returned by the handler determines whether or not the move conflict is resolved with default behavior. i.e. returning `false` will ensure no further action is taken, returning `true` will result in the default behavior and the method continuing.
|
||||
|
||||
For example:
|
||||
|
||||
|
||||
@@ -1323,7 +1323,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
|
||||
|
||||
|
||||
@@ -139,7 +139,8 @@ green and non-draggable regions will be colored red to aid debugging.
|
||||
|
||||
### `ELECTRON_DEBUG_NOTIFICATIONS`
|
||||
|
||||
Adds extra logs to [`Notification`](./notification.md) lifecycles on macOS to aid in debugging. Extra logging will be displayed when new Notifications are created or activated. They will also be displayed when common actions are taken: a notification is shown, dismissed, its button is clicked, or it is replied to.
|
||||
Adds extra logs to [`Notification`](./notification.md) lifecycles on macOS to aid in debugging. Extra logging will be displayed when new Notifications are created or activated. They will also be displayed when common a
|
||||
tions are taken: a notification is shown, dismissed, its button is clicked, or it is replied to.
|
||||
|
||||
Sample output:
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ console.log(image)
|
||||
* `options` Object
|
||||
* `width` Integer
|
||||
* `height` Integer
|
||||
* `scaleFactor` Number (optional) - Defaults to 1.0.
|
||||
* `scaleFactor` Double (optional) - Defaults to 1.0.
|
||||
|
||||
Returns `NativeImage`
|
||||
|
||||
@@ -162,7 +162,7 @@ pixel data returned by `toBitmap()`. The specific format is platform-dependent.
|
||||
* `options` Object (optional)
|
||||
* `width` Integer (optional) - Required for bitmap buffers.
|
||||
* `height` Integer (optional) - Required for bitmap buffers.
|
||||
* `scaleFactor` Number (optional) - Defaults to 1.0.
|
||||
* `scaleFactor` Double (optional) - Defaults to 1.0.
|
||||
|
||||
Returns `NativeImage`
|
||||
|
||||
@@ -225,7 +225,7 @@ The following methods are available on instances of the `NativeImage` class:
|
||||
#### `image.toPNG([options])`
|
||||
|
||||
* `options` Object (optional)
|
||||
* `scaleFactor` Number (optional) - Defaults to 1.0.
|
||||
* `scaleFactor` Double (optional) - Defaults to 1.0.
|
||||
|
||||
Returns `Buffer` - A [Buffer][buffer] that contains the image's `PNG` encoded data.
|
||||
|
||||
@@ -238,7 +238,7 @@ Returns `Buffer` - A [Buffer][buffer] that contains the image's `JPEG` encoded d
|
||||
#### `image.toBitmap([options])`
|
||||
|
||||
* `options` Object (optional)
|
||||
* `scaleFactor` Number (optional) - Defaults to 1.0.
|
||||
* `scaleFactor` Double (optional) - Defaults to 1.0.
|
||||
|
||||
Returns `Buffer` - A [Buffer][buffer] that contains a copy of the image's raw bitmap pixel
|
||||
data.
|
||||
@@ -246,14 +246,14 @@ data.
|
||||
#### `image.toDataURL([options])`
|
||||
|
||||
* `options` Object (optional)
|
||||
* `scaleFactor` Number (optional) - Defaults to 1.0.
|
||||
* `scaleFactor` Double (optional) - Defaults to 1.0.
|
||||
|
||||
Returns `string` - The data URL of the image.
|
||||
|
||||
#### `image.getBitmap([options])`
|
||||
|
||||
* `options` Object (optional)
|
||||
* `scaleFactor` Number (optional) - Defaults to 1.0.
|
||||
* `scaleFactor` Double (optional) - Defaults to 1.0.
|
||||
|
||||
Returns `Buffer` - A [Buffer][buffer] that contains the image's raw bitmap pixel data.
|
||||
|
||||
@@ -276,7 +276,7 @@ Returns `boolean` - Whether the image is empty.
|
||||
|
||||
#### `image.getSize([scaleFactor])`
|
||||
|
||||
* `scaleFactor` Number (optional) - Defaults to 1.0.
|
||||
* `scaleFactor` Double (optional) - Defaults to 1.0.
|
||||
|
||||
Returns [`Size`](structures/size.md).
|
||||
|
||||
@@ -317,20 +317,20 @@ will be preserved in the resized image.
|
||||
|
||||
#### `image.getAspectRatio([scaleFactor])`
|
||||
|
||||
* `scaleFactor` Number (optional) - Defaults to 1.0.
|
||||
* `scaleFactor` Double (optional) - Defaults to 1.0.
|
||||
|
||||
Returns `Number` - The image's aspect ratio.
|
||||
Returns `Float` - The image's aspect ratio.
|
||||
|
||||
If `scaleFactor` is passed, this will return the aspect ratio corresponding to the image representation most closely matching the passed value.
|
||||
|
||||
#### `image.getScaleFactors()`
|
||||
|
||||
Returns `Number[]` - An array of all scale factors corresponding to representations for a given nativeImage.
|
||||
Returns `Float[]` - An array of all scale factors corresponding to representations for a given nativeImage.
|
||||
|
||||
#### `image.addRepresentation(options)`
|
||||
|
||||
* `options` Object
|
||||
* `scaleFactor` Number (optional) - The scale factor to add the image representation for.
|
||||
* `scaleFactor` Double - The scale factor to add the image representation for.
|
||||
* `width` Integer (optional) - Defaults to 0. Required if a bitmap buffer
|
||||
is specified as `buffer`.
|
||||
* `height` Integer (optional) - Defaults to 0. Required if a bitmap buffer
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
# pushNotifications
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
> Register for and receive notifications from remote push notification services
|
||||
|
||||
For example, when registering for push notifications via Apple push notification services (APNS):
|
||||
|
||||
```javascript
|
||||
const { pushNotifications, Notification } = require('electron')
|
||||
|
||||
pushNotifications.registerForAPNSNotifications().then((token) => {
|
||||
// forward token to your remote notification server
|
||||
})
|
||||
|
||||
pushNotifications.on('received-apns-notification', (event, userInfo) => {
|
||||
// generate a new Notification object with the relevant userInfo fields
|
||||
})
|
||||
```
|
||||
|
||||
## Events
|
||||
|
||||
The `pushNotification` module emits the following events:
|
||||
|
||||
#### Event: 'received-apns-notification' _macOS_
|
||||
|
||||
Returns:
|
||||
|
||||
* `userInfo` Record<String, any>
|
||||
|
||||
Emitted when the app receives a remote notification while running.
|
||||
See: https://developer.apple.com/documentation/appkit/nsapplicationdelegate/1428430-application?language=objc
|
||||
|
||||
## Methods
|
||||
|
||||
The `pushNotification` module has the following methods:
|
||||
|
||||
### `pushNotifications.registerForAPNSNotifications()` _macOS_
|
||||
|
||||
Returns `Promise<string>`
|
||||
|
||||
Registers the app with Apple Push Notification service (APNS) to receive [Badge, Sound, and Alert](https://developer.apple.com/documentation/appkit/sremotenotificationtype?language=objc) notifications. If registration is successful, the promise will be resolved with the APNS device token. Otherwise, the promise will be rejected with an error message.
|
||||
See: https://developer.apple.com/documentation/appkit/nsapplication/1428476-registerforremotenotificationtyp?language=objc
|
||||
|
||||
### `pushNotifications.unregisterForAPNSNotifications()` _macOS_
|
||||
|
||||
Unregisters the app from notifications received from APNS.
|
||||
See: https://developer.apple.com/documentation/appkit/nsapplication/1428747-unregisterforremotenotifications?language=objc
|
||||
@@ -281,7 +281,7 @@ Returns:
|
||||
* `event` Event
|
||||
* `details` Object
|
||||
* `device` [HIDDevice[]](structures/hid-device.md)
|
||||
* `origin` string (optional) - The origin that the device has been revoked from.
|
||||
* `frame` [WebFrameMain](web-frame-main.md)
|
||||
|
||||
Emitted after `HIDDevice.forget()` has been called. This event can be used
|
||||
to help maintain persistent storage of permissions when
|
||||
@@ -705,6 +705,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 +713,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 +1050,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
|
||||
|
||||
@@ -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])`
|
||||
|
||||
|
||||
@@ -1428,7 +1428,7 @@ Returns `Promise<PrinterInfo[]>` - Resolves with a [`PrinterInfo[]`](structures/
|
||||
* `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` and `width`.
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`.
|
||||
* `callback` Function (optional)
|
||||
* `success` boolean - Indicates success of the print call.
|
||||
* `failureReason` string - Error description called back if the print fails.
|
||||
@@ -1459,28 +1459,43 @@ win.webContents.print(options, (success, errorType) => {
|
||||
#### `contents.printToPDF(options)`
|
||||
|
||||
* `options` Object
|
||||
* `landscape` boolean (optional) - Paper orientation.`true` for landscape, `false` for portrait. Defaults to false.
|
||||
* `displayHeaderFooter` boolean (optional) - Whether to display header and footer. Defaults to false.
|
||||
* `printBackground` boolean (optional) - Whether to print background graphics. Defaults to false.
|
||||
* `scale` number(optional) - Scale of the webpage rendering. Defaults to 1.
|
||||
* `pageSize` string | Size (optional) - Specify page size of the generated PDF. Can be `A0`, `A1`, `A2`, `A3`,
|
||||
`A4`, `A5`, `A6`, `Legal`, `Letter`, `Tabloid`, `Ledger`, or an Object containing `height` and `width` in inches. Defaults to `Letter`.
|
||||
* `margins` Object (optional)
|
||||
* `top` number (optional) - Top margin in inches. Defaults to 1cm (~0.4 inches).
|
||||
* `bottom` number (optional) - Bottom margin in inches. Defaults to 1cm (~0.4 inches).
|
||||
* `left` number (optional) - Left margin in inches. Defaults to 1cm (~0.4 inches).
|
||||
* `right` number (optional) - Right margin in inches. Defaults to 1cm (~0.4 inches).
|
||||
* `pageRanges` string (optional) - Paper ranges to print, e.g., '1-5, 8, 11-13'. Defaults to the empty string, which means print all pages.
|
||||
* `headerTemplate` string (optional) - HTML template for the print header. Should be valid HTML markup with following classes used to inject printing values into them: `date` (formatted print date), `title` (document title), `url` (document location), `pageNumber` (current page number) and `totalPages` (total pages in the document). For example, `<span class=title></span>` would generate span containing the title.
|
||||
* `footerTemplate` string (optional) - HTML template for the print footer. Should use the same format as the `headerTemplate`.
|
||||
* `preferCSSPageSize` boolean (optional) - Whether or not to prefer page size as defined by css. Defaults to false, in which case the content will be scaled to fit the paper size.
|
||||
* `headerFooter` Record<string, string> (optional) - the header and footer for the PDF.
|
||||
* `title` string - The title for the PDF header.
|
||||
* `url` string - the url for the PDF footer.
|
||||
* `landscape` boolean (optional) - `true` for landscape, `false` for portrait.
|
||||
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
|
||||
default margin, 1 for no margin, and 2 for minimum margin.
|
||||
* `scaleFactor` number (optional) - The scale factor of the web page. Can range from 0 to 100.
|
||||
* `pageRanges` Record<string, number> (optional) - The page range to print.
|
||||
* `from` number - Index of the first page to print (0-based).
|
||||
* `to` number - Index of the last page to print (inclusive) (0-based).
|
||||
* `pageSize` string | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width` in microns.
|
||||
* `printBackground` boolean (optional) - Whether to print CSS backgrounds.
|
||||
* `printSelectionOnly` boolean (optional) - Whether to print selection only.
|
||||
|
||||
Returns `Promise<Buffer>` - Resolves with the generated PDF data.
|
||||
|
||||
Prints the window's web page as PDF.
|
||||
Prints window's web page as PDF with Chromium's preview printing custom
|
||||
settings.
|
||||
|
||||
The `landscape` will be ignored if `@page` CSS at-rule is used in the web page.
|
||||
|
||||
By default, an empty `options` will be regarded as:
|
||||
|
||||
```javascript
|
||||
{
|
||||
marginsType: 0,
|
||||
printBackground: false,
|
||||
printSelectionOnly: false,
|
||||
landscape: false,
|
||||
pageSize: 'A4',
|
||||
scaleFactor: 100
|
||||
}
|
||||
```
|
||||
|
||||
Use `page-break-before: always;` CSS style to force to print to a new page.
|
||||
|
||||
An example of `webContents.printToPDF`:
|
||||
|
||||
```javascript
|
||||
@@ -1489,7 +1504,7 @@ const fs = require('fs')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
|
||||
const win = new BrowserWindow()
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL('http://github.com')
|
||||
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
@@ -1506,8 +1521,6 @@ win.webContents.on('did-finish-load', () => {
|
||||
})
|
||||
```
|
||||
|
||||
See [Page.printToPdf](https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF) for more information.
|
||||
|
||||
#### `contents.addWorkSpace(path)`
|
||||
|
||||
* `path` string
|
||||
|
||||
@@ -565,21 +565,21 @@ Prints `webview`'s web page. Same as `webContents.print([options])`.
|
||||
### `<webview>.printToPDF(options)`
|
||||
|
||||
* `options` Object
|
||||
* `landscape` boolean (optional) - Paper orientation.`true` for landscape, `false` for portrait. Defaults to false.
|
||||
* `displayHeaderFooter` boolean (optional) - Whether to display header and footer. Defaults to false.
|
||||
* `printBackground` boolean (optional) - Whether to print background graphics. Defaults to false.
|
||||
* `scale` number(optional) - Scale of the webpage rendering. Defaults to 1.
|
||||
* `pageSize` string | Size (optional) - Specify page size of the generated PDF. Can be `A0`, `A1`, `A2`, `A3`,
|
||||
`A4`, `A5`, `A6`, `Legal`, `Letter`, `Tabloid`, `Ledger`, or an Object containing `height` and `width` in inches. Defaults to `Letter`.
|
||||
* `margins` Object (optional)
|
||||
* `top` number (optional) - Top margin in inches. Defaults to 1cm (~0.4 inches).
|
||||
* `bottom` number (optional) - Bottom margin in inches. Defaults to 1cm (~0.4 inches).
|
||||
* `left` number (optional) - Left margin in inches. Defaults to 1cm (~0.4 inches).
|
||||
* `right` number (optional) - Right margin in inches. Defaults to 1cm (~0.4 inches).
|
||||
* `pageRanges` string (optional) - Paper ranges to print, e.g., '1-5, 8, 11-13'. Defaults to the empty string, which means print all pages.
|
||||
* `headerTemplate` string (optional) - HTML template for the print header. Should be valid HTML markup with following classes used to inject printing values into them: `date` (formatted print date), `title` (document title), `url` (document location), `pageNumber` (current page number) and `totalPages` (total pages in the document). For example, `<span class=title></span>` would generate span containing the title.
|
||||
* `footerTemplate` string (optional) - HTML template for the print footer. Should use the same format as the `headerTemplate`.
|
||||
* `preferCSSPageSize` boolean (optional) - Whether or not to prefer page size as defined by css. Defaults to false, in which case the content will be scaled to fit the paper size.
|
||||
* `headerFooter` Record<string, string> (optional) - the header and footer for the PDF.
|
||||
* `title` string - The title for the PDF header.
|
||||
* `url` string - the url for the PDF footer.
|
||||
* `landscape` boolean (optional) - `true` for landscape, `false` for portrait.
|
||||
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
|
||||
default margin, 1 for no margin, and 2 for minimum margin.
|
||||
and `width` in microns.
|
||||
* `scaleFactor` number (optional) - The scale factor of the web page. Can range from 0 to 100.
|
||||
* `pageRanges` Record<string, number> (optional) - The page range to print. On macOS, only the first range is honored.
|
||||
* `from` number - Index of the first page to print (0-based).
|
||||
* `to` number - Index of the last page to print (inclusive) (0-based).
|
||||
* `pageSize` string | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
|
||||
* `printBackground` boolean (optional) - Whether to print CSS backgrounds.
|
||||
* `printSelectionOnly` boolean (optional) - Whether to print selection only.
|
||||
|
||||
Returns `Promise<Uint8Array>` - Resolves with the generated PDF data.
|
||||
|
||||
|
||||
@@ -14,68 +14,6 @@ This document uses the following convention to categorize breaking changes:
|
||||
|
||||
## Planned Breaking API Changes (20.0)
|
||||
|
||||
### Behavior Changed: V8 Memory Cage enabled
|
||||
|
||||
The V8 memory cage has been enabled, which has implications for native modules
|
||||
which wrap non-V8 memory with `ArrayBuffer` or `Buffer`. See the [blog post
|
||||
about the V8 memory cage](https://www.electronjs.org/blog/v8-memory-cage) for
|
||||
more details.
|
||||
|
||||
### API Changed: `webContents.printToPDF()`
|
||||
|
||||
`webContents.printToPDF()` has been modified to conform to [`Page.printToPDF`](https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF) in the Chrome DevTools Protocol. This has been changes in order to
|
||||
address changes upstream that made our previous implementation untenable and rife with bugs.
|
||||
|
||||
**Arguments Changed**
|
||||
|
||||
* `pageRanges`
|
||||
|
||||
**Arguments Removed**
|
||||
|
||||
* `printSelectionOnly`
|
||||
* `marginsType`
|
||||
* `headerFooter`
|
||||
* `scaleFactor`
|
||||
|
||||
**Arguments Added**
|
||||
|
||||
* `headerTemplate`
|
||||
* `footerTemplate`
|
||||
* `displayHeaderFooter`
|
||||
* `margins`
|
||||
* `scale`
|
||||
* `preferCSSPageSize`
|
||||
|
||||
```js
|
||||
// Main process
|
||||
const { webContents } = require('electron')
|
||||
|
||||
webContents.printToPDF({
|
||||
landscape: true,
|
||||
displayHeaderFooter: true,
|
||||
printBackground: true,
|
||||
scale: 2,
|
||||
pageSize: 'Ledger',
|
||||
margins: {
|
||||
top: 2,
|
||||
bottom: 2,
|
||||
left: 2,
|
||||
right: 2
|
||||
},
|
||||
pageRanges: '1-5, 8, 11-13',
|
||||
headerTemplate: '<h1>Title</h1>',
|
||||
footerTemplate: '<div><span class="pageNumber"></span></div>',
|
||||
preferCSSPageSize: true
|
||||
}).then(data => {
|
||||
fs.writeFile(pdfPath, data, (error) => {
|
||||
if (error) throw error
|
||||
console.log(`Wrote PDF successfully to ${pdfPath}`)
|
||||
})
|
||||
}).catch(error => {
|
||||
console.log(`Failed to write PDF to ${pdfPath}: `, error)
|
||||
})
|
||||
```
|
||||
|
||||
### Default Changed: renderers without `nodeIntegration: true` are sandboxed by default
|
||||
|
||||
Previously, renderers that specified a preload script defaulted to being
|
||||
@@ -96,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
|
||||
|
||||
## Planned Breaking API Changes (18.0)
|
||||
|
||||
@@ -1275,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.
|
||||
|
||||
@@ -64,7 +64,7 @@ If you want to add a new API module to Electron, you'll want to look in [creatin
|
||||
|
||||
Electron has a fully-fledged governance system that oversees activity in Electron and whose working groups are responsible for areas like APIs, releases, and upgrades to Electron's dependencies including Chromium and Node.js. Depending on how frequently and to what end you want to contribute, you may want to consider joining a working group.
|
||||
|
||||
Details about each group and their responsibilities can be found in the [governance repo](https://github.com/electron/governance).
|
||||
Details about each group and their reponsibilities can be found in the [governance repo](https://github.com/electron/governance).
|
||||
|
||||
## Patches in Electron
|
||||
|
||||
|
||||
@@ -47,10 +47,10 @@ $ sudo yum install clang dbus-devel gtk3-devel libnotify-devel \
|
||||
On Fedora, install the following libraries:
|
||||
|
||||
```sh
|
||||
$ sudo dnf install clang dbus-devel gperf gtk3-devel \
|
||||
libnotify-devel libgnome-keyring-devel libcap-devel \
|
||||
$ sudo dnf install clang dbus-devel gtk3-devel libnotify-devel \
|
||||
libgnome-keyring-devel xorg-x11-server-utils libcap-devel \
|
||||
cups-devel libXtst-devel alsa-lib-devel libXrandr-devel \
|
||||
nss-devel python-dbusmock
|
||||
nss-devel python-dbusmock openjdk-8-jre
|
||||
```
|
||||
|
||||
On Arch Linux / Manjaro, install the following libraries:
|
||||
|
||||
@@ -9,7 +9,7 @@ Some of the more common approaches are outlined below.
|
||||
|
||||
Chromium contains logging macros which can aid debugging by printing information to console in C++ and Objective-C++.
|
||||
|
||||
You might use this to print out variable values, function names, and line numbers, amongst other things.
|
||||
You might use this to print out variable values, function names, and line numbers, amonst other things.
|
||||
|
||||
Some examples:
|
||||
|
||||
@@ -25,7 +25,7 @@ See [logging.h](https://chromium.googlesource.com/chromium/src/base/+/refs/heads
|
||||
|
||||
## Printing Stacktraces
|
||||
|
||||
Chromium contains a helper to print stack traces to console without interrupting the program.
|
||||
Chromium contains a helper to print stack traces to console without interrrupting the program.
|
||||
|
||||
```cpp
|
||||
#include "base/debug/stack_trace.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
startDrag: (fileName) => {
|
||||
|
||||
@@ -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()})`;
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 190 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 70 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](https://www.electronforge.io). You can check out
|
||||
its documentation 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,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,18 +42,18 @@ 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.
|
||||
|
||||
Let's take a look at an example `package.json` 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.
|
||||
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.
|
||||
|
||||
```json title="package.json" {7}
|
||||
```json
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "0.0.1",
|
||||
@@ -74,7 +69,7 @@ but we recommend that you are explicit.
|
||||
},
|
||||
"osxNotarize": {
|
||||
"appleId": "felix@felix.fun",
|
||||
"appleIdPassword": "my-apple-id-password"
|
||||
"appleIdPassword": "my-apple-id-password",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,11 +77,11 @@ but we recommend that you are explicit.
|
||||
}
|
||||
```
|
||||
|
||||
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">
|
||||
@@ -109,7 +104,7 @@ 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 title="entitlements.plist"
|
||||
```xml
|
||||
<key>com.apple.security.device.audio-input</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.camera</key>
|
||||
@@ -118,26 +113,28 @@ need to add the following entitlements:
|
||||
|
||||
If these are not present in your app's entitlements when you invoke, for example:
|
||||
|
||||
```js title="main.js"
|
||||
```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.
|
||||
|
||||
### Using Electron Builder
|
||||
## `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).
|
||||
|
||||
### Using Electron Packager
|
||||
## `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')
|
||||
@@ -158,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">
|
||||
@@ -178,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:
|
||||
|
||||
@@ -193,140 +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
|
||||
|
||||
Once you have a code signing certificate file (`.pfx`), you can sign
|
||||
[Squirrel.Windows][maker-squirrel] and [MSI][maker-msi] installers in Electron Forge
|
||||
with the `certificateFile` and `certificatePassword` fields in their respective
|
||||
configuration objects.
|
||||
|
||||
For example, if you keep your Forge config in your `package.json` file and are
|
||||
creating a Squirrel.Windows installer:
|
||||
|
||||
```json {9-15} title='package.json'
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "0.0.1",
|
||||
//...
|
||||
"config": {
|
||||
"forge": {
|
||||
"packagerConfig": {},
|
||||
"makers": [
|
||||
{
|
||||
"name": "@electron-forge/maker-squirrel",
|
||||
"config": {
|
||||
"certificateFile": "./cert.pfx",
|
||||
"certificatePassword": "this-is-a-secret"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
@@ -43,7 +43,7 @@ the WebHID API:
|
||||
* [`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,
|
||||
the default behavior of Electron is to store granted device permission through
|
||||
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
|
||||
@@ -92,7 +92,7 @@ There are several additional APIs for working with the Web Serial API:
|
||||
* [`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,
|
||||
the default behavior of Electron is to store granted device permission through
|
||||
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-serial-port` event) and then read from that storage with
|
||||
|
||||
@@ -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
|
||||
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
|
||||
@@ -24,11 +24,10 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
| 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 | 🚫 |
|
||||
| 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 | ✅ |
|
||||
| 20.0.0 | 2022-May-26 | 2022-Jun-21 | 2022-Aug-02 | M104 | TBD | ✅ |
|
||||
|
||||
**Notes:**
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ npm install --save-dev electron@latest
|
||||
|
||||
There are several major changes from our 1.x strategy outlined below. Each change is intended to satisfy the needs and priorities of developers/maintainers and app developers.
|
||||
|
||||
1. Strict use of the [SemVer](#semver) spec
|
||||
1. Strict use of the the [SemVer](#semver) spec
|
||||
2. Introduction of semver-compliant `-beta` tags
|
||||
3. Introduction of [conventional commit messages](https://conventionalcommits.org/)
|
||||
4. Well-defined stabilization branches
|
||||
|
||||
@@ -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][discord] and let us know!
|
||||
|
||||
[discord]: https://discord.gg/electronjs
|
||||
[fiddle]: https://www.electronjs.org/fiddle
|
||||
@@ -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.gg/electronjs
|
||||
[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
|
||||
|
||||
@@ -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 = 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.messagePort 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.
|
||||
@@ -277,7 +213,9 @@ makeStreamingRequest(42, (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
|
||||
|
||||
@@ -22,6 +22,7 @@ In `preload.js` use the [`contextBridge`] to inject a method `window.electron.st
|
||||
|
||||
```js
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
startDrag: (fileName) => {
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
---
|
||||
title: 'Process Model'
|
||||
description: 'Electron inherits its multi-process architecture from Chromium, which makes the framework architecturally very similar to a modern web browser. This guide will expand on the concepts applied in the tutorial.'
|
||||
slug: process-model
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
# Process Model
|
||||
|
||||
Electron inherits its multi-process architecture from Chromium, which makes the framework
|
||||
architecturally very similar to a modern web browser. This guide will expand on the
|
||||
concepts applied in the [Tutorial][tutorial].
|
||||
architecturally very similar to a modern web browser. In this guide, we'll expound on
|
||||
the conceptual knowledge of Electron that we applied in the minimal [quick start app][].
|
||||
|
||||
[tutorial]: ./tutorial-1-prerequisites.md
|
||||
[quick start app]: ./quick-start.md
|
||||
|
||||
## Why not a single process?
|
||||
|
||||
@@ -34,10 +27,10 @@ visualizes this model:
|
||||

|
||||
|
||||
Electron applications are structured very similarly. As an app developer, you control
|
||||
two types of processes: [main](#the-main-process) and [renderer](#the-renderer-process).
|
||||
These are analogous to Chrome's own browser and renderer processes outlined above.
|
||||
two types of processes: main and renderer. These are analogous to Chrome's own browser
|
||||
and renderer processes outlined above.
|
||||
|
||||
[chrome comic]: https://www.google.com/googlebooks/chrome/
|
||||
[Chrome Comic]: https://www.google.com/googlebooks/chrome/
|
||||
|
||||
## The main process
|
||||
|
||||
@@ -47,7 +40,7 @@ to `require` modules and use all of Node.js APIs.
|
||||
|
||||
### Window management
|
||||
|
||||
The main process' primary purpose is to create and manage application windows with the
|
||||
The primary purpose of the main process is to create and manage application windows with the
|
||||
[`BrowserWindow`][browser-window] module.
|
||||
|
||||
Each instance of the `BrowserWindow` class creates an application window that loads
|
||||
@@ -75,7 +68,7 @@ When a `BrowserWindow` instance is destroyed, its corresponding renderer process
|
||||
terminated as well.
|
||||
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[web-embed]: ../tutorial/web-embeds.md
|
||||
[web-embed]: ./web-embeds.md
|
||||
[web-contents]: ../api/web-contents.md
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
|
||||
@@ -83,7 +76,7 @@ terminated as well.
|
||||
|
||||
The main process also controls your application's lifecycle through Electron's
|
||||
[`app`][app] module. This module provides a large set of events and methods
|
||||
that you can use to add custom application behaviour (for instance, programmatically
|
||||
that you can use to add custom application behaviour (for instance, programatically
|
||||
quitting your application, modifying the application dock, or showing an About panel).
|
||||
|
||||
As a practical example, the app shown in the [quick start guide][quick-start-lifecycle]
|
||||
@@ -97,7 +90,7 @@ app.on('window-all-closed', () => {
|
||||
```
|
||||
|
||||
[app]: ../api/app.md
|
||||
[quick-start-lifecycle]: ../tutorial/quick-start.md#manage-your-windows-lifecycle
|
||||
[quick-start-lifecycle]: ./quick-start.md#manage-your-windows-lifecycle
|
||||
|
||||
### Native APIs
|
||||
|
||||
@@ -112,7 +105,7 @@ For a full list of Electron's main process modules, check out our API documentat
|
||||
|
||||
Each Electron app spawns a separate renderer process for each open `BrowserWindow`
|
||||
(and each web embed). As its name implies, a renderer is responsible for
|
||||
_rendering_ web content. For all intents and purposes, code ran in renderer processes
|
||||
*rendering* web content. For all intents and purposes, code ran in renderer processes
|
||||
should behave according to web standards (insofar as Chromium does, at least).
|
||||
|
||||
Therefore, all user interfaces and app functionality within a single browser
|
||||
@@ -122,22 +115,18 @@ web.
|
||||
Although explaining every web spec is out of scope for this guide, the bare minimum
|
||||
to understand is:
|
||||
|
||||
- An HTML file is your entry point for the renderer process.
|
||||
- UI styling is added through Cascading Style Sheets (CSS).
|
||||
- Executable JavaScript code can be added through `<script>` elements.
|
||||
* An HTML file is your entry point for the renderer process.
|
||||
* UI styling is added through Cascading Style Sheets (CSS).
|
||||
* Executable JavaScript code can be added through `<script>` elements.
|
||||
|
||||
Moreover, this also means that the renderer has no direct access to `require`
|
||||
or other Node.js APIs. In order to directly include NPM modules in the renderer,
|
||||
you must use the same bundler toolchains (for example, `webpack` or `parcel`) that you
|
||||
use on the web.
|
||||
|
||||
:::warning
|
||||
|
||||
Renderer processes can be spawned with a full Node.js environment for ease of
|
||||
development. Historically, this used to be the default, but this feature was disabled
|
||||
for security reasons.
|
||||
|
||||
:::
|
||||
> Note: Renderer processes can be spawned with a full Node.js environment for ease of
|
||||
> development. Historically, this used to be the default, but this feature was disabled
|
||||
> for security reasons.
|
||||
|
||||
At this point, you might be wondering how your renderer process user interfaces
|
||||
can interact with Node.js and Electron's native desktop functionality if these
|
||||
@@ -146,9 +135,8 @@ way to import Electron's content scripts.
|
||||
|
||||
## Preload scripts
|
||||
|
||||
<!-- Note: This guide doesn't take sandboxing into account, which might fundamentally
|
||||
<!-- Note: This guide doesn't take sandboxing into account, which might fundamentally
|
||||
change the statements here. -->
|
||||
|
||||
Preload scripts contain code that executes in a renderer process before its web content
|
||||
begins loading. These scripts run within the renderer context, but are granted more
|
||||
privileges by having access to Node.js APIs.
|
||||
@@ -161,8 +149,8 @@ const { BrowserWindow } = require('electron')
|
||||
//...
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: 'path/to/preload.js',
|
||||
},
|
||||
preload: 'path/to/preload.js'
|
||||
}
|
||||
})
|
||||
//...
|
||||
```
|
||||
@@ -177,7 +165,7 @@ the [`contextIsolation`][context-isolation] default.
|
||||
|
||||
```js title='preload.js'
|
||||
window.myAPI = {
|
||||
desktop: true,
|
||||
desktop: true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -196,7 +184,7 @@ securely:
|
||||
const { contextBridge } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('myAPI', {
|
||||
desktop: true,
|
||||
desktop: true
|
||||
})
|
||||
```
|
||||
|
||||
@@ -207,15 +195,14 @@ console.log(window.myAPI)
|
||||
|
||||
This feature is incredibly useful for two main purposes:
|
||||
|
||||
- By exposing [`ipcRenderer`][ipcrenderer] helpers to the renderer, you can use
|
||||
* By exposing [`ipcRenderer`][ipcRenderer] helpers to the renderer, you can use
|
||||
inter-process communication (IPC) to trigger main process tasks from the
|
||||
renderer (and vice-versa).
|
||||
- If you're developing an Electron wrapper for an existing web app hosted on a remote
|
||||
* If you're developing an Electron wrapper for an existing web app hosted on a remote
|
||||
URL, you can add custom properties onto the renderer's `window` global that can
|
||||
be used for desktop-only logic on the web client's side.
|
||||
|
||||
[window-mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Window
|
||||
[context-isolation]: ./context-isolation.md
|
||||
[context-bridge]: ../api/context-bridge.md
|
||||
[ipcrenderer]: ../api/ipc-renderer.md
|
||||
[tutorial]: ./tutorial-1-prerequisites.md
|
||||
[ipcRenderer]: ../api/ipc-renderer.md
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
---
|
||||
title: 'Prerequisites'
|
||||
description: 'This guide will step you through the process of creating a barebones Hello World app in Electron, similar to electron/electron-quick-start.'
|
||||
slug: tutorial-prerequisites
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
:::info Follow along the tutorial
|
||||
|
||||
This is **part 1** of the Electron tutorial.
|
||||
|
||||
1. **[Prerequisites][prerequisites]**
|
||||
1. [Building your First App][building your first app]
|
||||
1. [Using Preload Scripts][preload]
|
||||
1. [Adding Features][features]
|
||||
1. [Packaging Your Application][packaging]
|
||||
1. [Publishing and Updating][updates]
|
||||
|
||||
:::
|
||||
|
||||
Electron is a framework for building desktop applications using JavaScript,
|
||||
HTML, and CSS. By embedding [Chromium][chromium] and [Node.js][node] into a
|
||||
single binary file, Electron allows you to create cross-platform apps that
|
||||
work on Windows, macOS, and Linux with a single JavaScript codebase.
|
||||
|
||||
This tutorial will guide you through the process of developing a desktop
|
||||
application with Electron and distributing it to end users.
|
||||
|
||||
## Assumptions
|
||||
|
||||
Electron is a native wrapper layer for web apps and is run in a Node.js environment.
|
||||
Therefore, this tutorial assumes you are generally familiar with Node and
|
||||
front-end web development basics. If you need to do some background reading before
|
||||
continuing, we recommend the following resources:
|
||||
|
||||
- [Getting started with the Web (MDN Web Docs)][mdn-guide]
|
||||
- [Introduction to Node.js][node-guide]
|
||||
|
||||
## Required tools
|
||||
|
||||
### Code editor
|
||||
|
||||
You will need a text editor to write your code. We recommend using [Visual Studio Code],
|
||||
although you can choose whichever one you prefer.
|
||||
|
||||
### Command line
|
||||
|
||||
Throughout the tutorial, we will ask you to use various command-line interfaces (CLIs). You can
|
||||
type these commands into your system's default terminal:
|
||||
|
||||
- Windows: Command Prompt or PowerShell
|
||||
- macOS: Terminal
|
||||
- Linux: varies depending on distribution (e.g. GNOME Terminal, Konsole)
|
||||
|
||||
Most code editors also come with an integrated terminal, which you can also use.
|
||||
|
||||
### Git and GitHub
|
||||
|
||||
Git is a commonly-used version control system for source code, and GitHub is a collaborative
|
||||
development platform built on top of it. Although neither is strictly necessary to building
|
||||
an Electron application, we will use GitHub releases to set up automatic updates later
|
||||
on in the tutorial. Therefore, we'll require you to:
|
||||
|
||||
- [Create a GitHub account](https://github.com/join)
|
||||
- [Install Git](https://github.com/git-guides/install-git)
|
||||
|
||||
If you're unfamiliar with how Git works, we recommend reading GitHub's [Git guides]. You can also
|
||||
use the [GitHub Desktop] app if you prefer using a visual interface over the command line.
|
||||
|
||||
We recommend that you create a local Git repository and publish it to GitHub before starting
|
||||
the tutorial, and commit your code after every step.
|
||||
|
||||
:::info Installing Git via GitHub Desktop
|
||||
|
||||
GitHub Desktop will install the latest version of Git on your system if you don't already have
|
||||
it installed.
|
||||
|
||||
:::
|
||||
|
||||
### Node.js and npm
|
||||
|
||||
To begin developing an Electron app, you need to install the [Node.js][node-download]
|
||||
runtime and its bundled npm package manager onto your system. We recommend that you
|
||||
use the latest long-term support (LTS) version.
|
||||
|
||||
:::tip
|
||||
|
||||
Please install Node.js using pre-built installers for your platform.
|
||||
You may encounter incompatibility issues with different development tools otherwise.
|
||||
If you are using macOS, we recommend using a package manager like [Homebrew] or
|
||||
[nvm] to avoid any directory permission issues.
|
||||
|
||||
:::
|
||||
|
||||
To check that Node.js was installed correctly, you can use the `-v` flag when
|
||||
running the `node` and `npm` commands. These should print out the installed
|
||||
versions.
|
||||
|
||||
```sh
|
||||
$ node -v
|
||||
v16.14.2
|
||||
$ npm -v
|
||||
8.7.0
|
||||
```
|
||||
|
||||
:::caution
|
||||
|
||||
Although you need Node.js installed locally to scaffold an Electron project,
|
||||
Electron **does not use your system's Node.js installation to run its code**. Instead, it
|
||||
comes bundled with its own Node.js runtime. This means that your end users do not
|
||||
need to install Node.js themselves as a prerequisite to running your app.
|
||||
|
||||
To check which version of Node.js is running in your app, you can access the global
|
||||
[`process.versions`] variable in the main process or preload script. You can also reference
|
||||
the list of versions in the [electron/releases] repository.
|
||||
|
||||
:::
|
||||
|
||||
<!-- Links -->
|
||||
|
||||
[chromium]: https://www.chromium.org/
|
||||
[electron/releases]: https://github.com/electron/releases/blob/master/readme.md#releases
|
||||
[homebrew]: https://brew.sh/
|
||||
[mdn-guide]: https://developer.mozilla.org/en-US/docs/Learn/
|
||||
[node]: https://nodejs.org/
|
||||
[node-guide]: https://nodejs.dev/learn
|
||||
[node-download]: https://nodejs.org/en/download/
|
||||
[nvm]: https://github.com/nvm-sh/nvm
|
||||
[process-model]: ./process-model.md
|
||||
[`process.versions`]: https://nodejs.org/api/process.html#processversions
|
||||
[github]: https://github.com/
|
||||
[git guides]: https://github.com/git-guides/
|
||||
[github desktop]: https://desktop.github.com/
|
||||
[visual studio code]: https://code.visualstudio.com/
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
[prerequisites]: tutorial-1-prerequisites.md
|
||||
[building your first app]: tutorial-2-first-app.md
|
||||
[preload]: tutorial-3-preload.md
|
||||
[features]: tutorial-4-adding-features.md
|
||||
[packaging]: tutorial-5-packaging.md
|
||||
[updates]: tutorial-6-publishing-updating.md
|
||||
@@ -1,480 +0,0 @@
|
||||
---
|
||||
title: 'Building your First App'
|
||||
description: 'This guide will step you through the process of creating a barebones Hello World app in Electron, similar to electron/electron-quick-start.'
|
||||
slug: tutorial-first-app
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
:::info Follow along the tutorial
|
||||
|
||||
This is **part 2** of the Electron tutorial.
|
||||
|
||||
1. [Prerequisites][prerequisites]
|
||||
1. **[Building your First App][building your first app]**
|
||||
1. [Using Preload Scripts][preload]
|
||||
1. [Adding Features][features]
|
||||
1. [Packaging Your Application][packaging]
|
||||
1. [Publishing and Updating][updates]
|
||||
|
||||
:::
|
||||
|
||||
## Learning goals
|
||||
|
||||
In this part of the tutorial, you will learn how to set up your Electron project
|
||||
and write a minimal starter application. By the end of this section,
|
||||
you should be able to run a working Electron app in development mode from
|
||||
your terminal.
|
||||
|
||||
## Setting up your project
|
||||
|
||||
:::caution Avoid WSL
|
||||
|
||||
If you are on a Windows machine, please do not use [Windows Subsystem for Linux][wsl] (WSL)
|
||||
when following this tutorial as you will run into issues when trying to execute the
|
||||
application.
|
||||
|
||||
<!--https://www.electronforge.io/guides/developing-with-wsl-->
|
||||
|
||||
:::
|
||||
|
||||
### Initializing your npm project
|
||||
|
||||
Electron apps are scaffolded using npm, with the package.json file
|
||||
as an entry point. Start by creating a folder and initializing an npm package
|
||||
within it with `npm init`.
|
||||
|
||||
```sh npm2yarn
|
||||
mkdir my-electron-app && cd my-electron-app
|
||||
npm init
|
||||
```
|
||||
|
||||
This command will prompt you to configure some fields in your package.json.
|
||||
There are a few rules to follow for the purposes of this tutorial:
|
||||
|
||||
- _entry point_ should be `main.js` (you will be creating that file soon).
|
||||
- _author_, _license_, and _description_ can be any value, but will be necessary for
|
||||
[packaging][packaging] later on.
|
||||
|
||||
Then, install Electron into your app's **devDependencies**, which is the list of external
|
||||
development-only package dependencies not required in production.
|
||||
|
||||
:::info Why is Electron a devDependency?
|
||||
|
||||
This may seem counter-intuitive since your production code is running Electron APIs.
|
||||
However, packaged apps will come bundled with the Electron binary, eliminating the need to specify
|
||||
it as a production dependency.
|
||||
|
||||
:::
|
||||
|
||||
```sh npm2yarn
|
||||
npm install electron --save-dev
|
||||
```
|
||||
|
||||
Your package.json file should look something like this after initializing your package
|
||||
and installing Electron. You should also now have a `node_modules` folder containing
|
||||
the Electron executable, as well as a `package-lock.json` lockfile that specifies
|
||||
the exact dependency versions to install.
|
||||
|
||||
```json title='package.json'
|
||||
{
|
||||
"name": "my-electron-app",
|
||||
"version": "1.0.0",
|
||||
"description": "Hello World!",
|
||||
"main": "main.js",
|
||||
"author": "Jane Doe",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"electron": "19.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::info Advanced Electron installation steps
|
||||
|
||||
If installing Electron directly fails, please refer to our [Advanced Installation][installation]
|
||||
documentation for instructions on download mirrors, proxies, and troubleshooting steps.
|
||||
|
||||
:::
|
||||
|
||||
### Adding a .gitignore
|
||||
|
||||
The [`.gitignore`][gitignore] file specifies which files and directories to avoid tracking
|
||||
with Git. You should place a copy of [GitHub's Node.js gitignore template][gitignore-template]
|
||||
into your project's root folder to avoid committing your project's `node_modules` folder.
|
||||
|
||||
## Running an Electron app
|
||||
|
||||
:::tip Further reading
|
||||
|
||||
Read [Electron's process model][process-model] documentation to better
|
||||
understand how Electron's multiple processes work together.
|
||||
|
||||
:::
|
||||
|
||||
The [`main`][package-json-main] script you defined in package.json is the entry point of any
|
||||
Electron application. This script controls the **main process**, which runs in a Node.js
|
||||
environment and is responsible for controlling your app's lifecycle, displaying native
|
||||
interfaces, performing privileged operations, and managing renderer processes
|
||||
(more on that later).
|
||||
|
||||
Before creating your first Electron app, you will first use a trivial script to ensure your
|
||||
main process entry point is configured correctly. Create a `main.js` file in the root folder
|
||||
of your project with a single line of code:
|
||||
|
||||
```js title='main.js'
|
||||
console.log(`Hello from Electron 👋`)
|
||||
```
|
||||
|
||||
Because Electron's main process is a Node.js runtime, you can execute arbitrary Node.js code
|
||||
with the `electron` command (you can even use it as a [REPL]). To execute this script,
|
||||
add `electron .` to the `start` command in the [`scripts`][package-scripts]
|
||||
field of your package.json. This command will tell the Electron executable to look for the main
|
||||
script in the current directory and run it in dev mode.
|
||||
|
||||
```json {8-10} title='package.json'
|
||||
{
|
||||
"name": "my-electron-app",
|
||||
"version": "1.0.0",
|
||||
"description": "Hello World!",
|
||||
"main": "main.js",
|
||||
"author": "Jane Doe",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"start": "electron ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^19.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```sh npm2yarn
|
||||
npm run start
|
||||
```
|
||||
|
||||
Your terminal should print out `Hello from Electron 👋`. Congratulations,
|
||||
you have executed your first line of code in Electron! Next, you will learn
|
||||
how to create user interfaces with HTML and load that into a native window.
|
||||
|
||||
## Loading a web page into a BrowserWindow
|
||||
|
||||
In Electron, each window displays a web page that can be loaded either from a local HTML
|
||||
file or a remote web address. For this example, you will be loading in a local file. Start
|
||||
by creating a barebones web page in an `index.html` file in the root folder of your project:
|
||||
|
||||
```html title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<meta
|
||||
http-equiv="X-Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'"
|
||||
/>
|
||||
<title>Hello from Electron renderer!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello from Electron renderer!</h1>
|
||||
<p>👋</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Now that you have a web page, you can load it into an Electron [BrowserWindow][browser-window].
|
||||
Replace the contents your `main.js` file with the following code. We will explain each
|
||||
highlighted block separately.
|
||||
|
||||
```js {1,3-10,12-14} title='main.js' showLineNumbers
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
```
|
||||
|
||||
### Importing modules
|
||||
|
||||
```js title='main.js (Line 1)'
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
```
|
||||
|
||||
In the first line, we are importing two Electron modules
|
||||
with CommonJS module syntax:
|
||||
|
||||
- [app][app], which controls your application's event lifecycle.
|
||||
- [BrowserWindow][browser-window], which creates and manages app windows.
|
||||
|
||||
:::info Capitalization conventions
|
||||
|
||||
You might have noticed the capitalization difference between the **a**pp
|
||||
and **B**rowser**W**indow modules. Electron follows typical JavaScript conventions here,
|
||||
where PascalCase modules are instantiable class constructors (e.g. BrowserWindow, Tray,
|
||||
Notification) whereas camelCase modules are not instantiable (e.g. app, ipcRenderer, webContents).
|
||||
|
||||
:::
|
||||
|
||||
:::warning ES Modules in Electron
|
||||
|
||||
[ECMAScript modules](https://nodejs.org/api/esm.html) (i.e. using `import` to load a module)
|
||||
are currently not directly supported in Electron. You can find more information about the
|
||||
state of ESM in Electron in [electron/electron#21457](https://github.com/electron/electron/issues/21457).
|
||||
|
||||
:::
|
||||
|
||||
### Writing a reusable function to instantiate windows
|
||||
|
||||
The `createWindow()` function loads your web page into a new BrowserWindow instance:
|
||||
|
||||
```js title='main.js (Lines 3-10)'
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
```
|
||||
|
||||
### Calling your function when the app is ready
|
||||
|
||||
```js title='main.js (Lines 12-14)'
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
```
|
||||
|
||||
Many of Electron's core modules are Node.js [event emitters] that adhere to Node's asynchronous
|
||||
event-driven architecture. The app module is one of these emitters.
|
||||
|
||||
In Electron, BrowserWindows can only be created after the app module's [`ready`][app-ready] event
|
||||
is fired. You can wait for this event by using the [`app.whenReady()`][app-when-ready] API and
|
||||
calling `createWindow()` once its promise is fulfilled.
|
||||
|
||||
:::info
|
||||
|
||||
You typically listen to Node.js events by using an emitter's `.on` function.
|
||||
|
||||
```diff
|
||||
+ app.on('ready').then(() => {
|
||||
- app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
```
|
||||
|
||||
However, Electron exposes `app.whenReady()` as a helper specifically for the `ready` event to
|
||||
avoid subtle pitfalls with directly listening to that event in particular.
|
||||
See [electron/electron#21972](https://github.com/electron/electron/pull/21972) for details.
|
||||
|
||||
:::
|
||||
|
||||
At this point, running your Electron application's `start` command should successfully
|
||||
open a window that displays your web page!
|
||||
|
||||
Each web page your app displays in a window will run in a separate process called a
|
||||
**renderer** process (or simply _renderer_ for short). Renderer processes have access
|
||||
to the same JavaScript APIs and tooling you use for typical front-end web
|
||||
development, such as using [webpack] to bundle and minify your code or [React][react]
|
||||
to build your user interfaces.
|
||||
|
||||
## Managing your app's window lifecycle
|
||||
|
||||
Application windows behave differently on each operating system. Rather than
|
||||
enforce these conventions by default, Electron gives you the choice to implement
|
||||
them in your app code if you wish to follow them. You can implement basic window
|
||||
conventions by listening for events emitted by the app and BrowserWindow modules.
|
||||
|
||||
:::tip Process-specific control flow
|
||||
|
||||
Checking against Node's [`process.platform`][node-platform] variable can help you
|
||||
to run code conditionally on certain platforms. Note that there are only three
|
||||
possible platforms that Electron can run in: `win32` (Windows), `linux` (Linux),
|
||||
and `darwin` (macOS).
|
||||
|
||||
:::
|
||||
|
||||
### Quit the app when all windows are closed (Windows & Linux)
|
||||
|
||||
On Windows and Linux, closing all windows will generally quit an application entirely.
|
||||
To implement this pattern in your Electron app, listen for the app module's
|
||||
[`window-all-closed`][window-all-closed] event, and call [`app.quit()`][app-quit]
|
||||
to exit your app if the user is not on macOS.
|
||||
|
||||
```js
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
```
|
||||
|
||||
### Open a window if none are open (macOS)
|
||||
|
||||
In contrast, macOS apps generally continue running even without any windows open.
|
||||
Activating the app when no windows are available should open a new one.
|
||||
|
||||
To implement this feature, listen for the app module's [`activate`][activate]
|
||||
event, and call your existing `createWindow()` method if no BrowserWindows are open.
|
||||
|
||||
Because windows cannot be created before the `ready` event, you should only listen for
|
||||
`activate` events after your app is initialized. Do this by only listening for activate
|
||||
events inside your existing `whenReady()` callback.
|
||||
|
||||
```js
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Final starter code
|
||||
|
||||
```fiddle docs/fiddles/tutorial-first-app
|
||||
|
||||
```
|
||||
|
||||
## Optional: Debugging from VS Code
|
||||
|
||||
If you want to debug your application using VS Code, you need to attach VS Code to
|
||||
both the main and renderer processes. Here is a sample configuration for you to
|
||||
run. Create a launch.json configuration in a new `.vscode` folder in your project:
|
||||
|
||||
```json title='.vscode/launch.json'
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Main + renderer",
|
||||
"configurations": ["Main", "Renderer"],
|
||||
"stopAll": true
|
||||
}
|
||||
],
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Renderer",
|
||||
"port": 9222,
|
||||
"request": "attach",
|
||||
"type": "pwa-chrome",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"name": "Main",
|
||||
"type": "pwa-node",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
|
||||
"windows": {
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
|
||||
},
|
||||
"args": [".", "--remote-debugging-port=9222"],
|
||||
"outputCapture": "std",
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The "Main + renderer" option will appear when you select "Run and Debug"
|
||||
from the sidebar, allowing you to set breakpoints and inspect all the variables among
|
||||
other things in both the main and renderer processes.
|
||||
|
||||
What we have done in the `launch.json` file is to create 3 configurations:
|
||||
|
||||
- `Main` is used to start the main process and also expose port 9222 for remote debugging
|
||||
(`--remote-debugging-port=9222`). This is the port that we will use to attach the debugger
|
||||
for the `Renderer`. Because the main process is a Node.js process, the type is set to
|
||||
`pwa-node` (`pwa-` is the prefix that tells VS Code to use the latest JavaScript debugger).
|
||||
- `Renderer` is used to debug the renderer process. Because the main process is the one
|
||||
that creates the process, we have to "attach" to it (`"request": "attach"`) instead of
|
||||
creating a new one.
|
||||
The renderer process is a web one, so the debugger we have to use is `pwa-chrome`.
|
||||
- `Main + renderer` is a [compound task] that executes the previous ones simultaneously.
|
||||
|
||||
:::caution
|
||||
|
||||
Because we are attaching to a process in `Renderer`, it is possible that the first lines of
|
||||
your code will be skipped as the debugger will not have had enough time to connect before they are
|
||||
being executed.
|
||||
You can work around this by refreshing the page or setting a timeout before executing the code
|
||||
in development mode.
|
||||
|
||||
:::
|
||||
|
||||
:::info Further reading
|
||||
|
||||
If you want to dig deeper in the debugging area, the following guides provide more information:
|
||||
|
||||
- [Application Debugging]
|
||||
- [DevTools Extensions][devtools extension]
|
||||
|
||||
:::
|
||||
|
||||
## Summary
|
||||
|
||||
Electron applications are set up using npm packages. The Electron executable should be installed
|
||||
in your project's `devDependencies` and can be run in development mode using a script in your
|
||||
package.json file.
|
||||
|
||||
The executable runs the JavaScript entry point found in the `main` property of your package.json.
|
||||
This file controls Electron's **main process**, which runs an instance of Node.js and is
|
||||
responsible for your app's lifecycle, displaying native interfaces, performing privileged operations,
|
||||
and managing renderer processes.
|
||||
|
||||
**Renderer processes** (or renderers for short) are responsible for display graphical content. You can
|
||||
load a web page into a renderer by pointing it to either a web address or a local HTML file.
|
||||
Renderers behave very similarly to regular web pages and have access to the same web APIs.
|
||||
|
||||
In the next section of the tutorial, we will be learning how to augment the renderer process with
|
||||
privileged APIs and how to communicate between processes.
|
||||
|
||||
<!-- Links -->
|
||||
|
||||
[activate]: ../api/app.md#event-activate-macos
|
||||
[advanced-installation]: installation.md
|
||||
[app]: ../api/app.md
|
||||
[app-quit]: ../api/app.md#appquit
|
||||
[app-ready]: ../api/app.md#event-ready
|
||||
[app-when-ready]: ../api/app.md#appwhenready
|
||||
[application debugging]: ./application-debugging.md
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[commonjs]: https://nodejs.org/docs/../api/modules.html#modules_modules_commonjs_modules
|
||||
[compound task]: https://code.visualstudio.com/Docs/editor/tasks#_compound-tasks
|
||||
[devtools extension]: ./devtools-extension.md
|
||||
[event emitters]: https://nodejs.org/api/events.html#events
|
||||
[gitignore]: https://git-scm.com/docs/gitignore
|
||||
[gitignore-template]: https://github.com/github/gitignore/blob/main/Node.gitignore
|
||||
[installation]: ./installation.md
|
||||
[node-platform]: https://nodejs.org/api/process.html#process_process_platform
|
||||
[package-json-main]: https://docs.npmjs.com/cli/v7/configuring-npm/package-json#main
|
||||
[package-scripts]: https://docs.npmjs.com/cli/v7/using-npm/scripts
|
||||
[process-model]: process-model.md
|
||||
[react]: https://reactjs.org
|
||||
[repl]: ./repl.md
|
||||
[sandbox]: ./sandbox.md
|
||||
[webpack]: https://webpack.js.org
|
||||
[window-all-closed]: ../api/app.md#event-window-all-closed
|
||||
[wsl]: https://docs.microsoft.com/en-us/windows/wsl/about#what-is-wsl-2
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
[prerequisites]: tutorial-1-prerequisites.md
|
||||
[building your first app]: tutorial-2-first-app.md
|
||||
[preload]: tutorial-3-preload.md
|
||||
[features]: tutorial-4-adding-features.md
|
||||
[packaging]: tutorial-5-packaging.md
|
||||
[updates]: tutorial-6-publishing-updating.md
|
||||
@@ -1,271 +0,0 @@
|
||||
---
|
||||
title: 'Using Preload Scripts'
|
||||
description: 'This guide will step you through the process of creating a barebones Hello World app in Electron, similar to electron/electron-quick-start.'
|
||||
slug: tutorial-preload
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
:::info Follow along the tutorial
|
||||
|
||||
This is **part 3** of the Electron tutorial.
|
||||
|
||||
1. [Prerequisites][prerequisites]
|
||||
1. [Building your First App][building your first app]
|
||||
1. **[Using Preload Scripts][preload]**
|
||||
1. [Adding Features][features]
|
||||
1. [Packaging Your Application][packaging]
|
||||
1. [Publishing and Updating][updates]
|
||||
|
||||
:::
|
||||
|
||||
## Learning goals
|
||||
|
||||
In this part of the tutorial, you will learn what a preload script is and how to use one
|
||||
to securely expose privileged APIs into the renderer process. You will also learn how to
|
||||
communicate between main and renderer processes with Electron's inter-process
|
||||
communication (IPC) modules.
|
||||
|
||||
## What is a preload script?
|
||||
|
||||
Electron's main process is a Node.js environment that has full operating system access.
|
||||
On top of [Electron modules][modules], you can also access [Node.js built-ins][node-api],
|
||||
as well as any packages installed via npm. On the other hand, renderer processes run web
|
||||
pages and do not run Node.js by default for security reasons.
|
||||
|
||||
To bridge Electron's different process types together, we will need to use a special script
|
||||
called a **preload**.
|
||||
|
||||
## Augmenting the renderer with a preload script
|
||||
|
||||
A BrowserWindow's preload script runs in a context that has access to both the HTML DOM
|
||||
and a Node.js environment. Preload scripts are injected before a web page loads in the renderer,
|
||||
similar to a Chrome extension's [content scripts][content-script]. To add features to your renderer
|
||||
that require privileged access, you can define [global] objects through the
|
||||
[contextBridge][contextbridge] API.
|
||||
|
||||
To demonstrate this concept, you will create a preload script that exposes your app's
|
||||
versions of Chrome, Node, and Electron into the renderer.
|
||||
|
||||
Add a new `preload.js` script that exposes selected properties of Electron's `process.versions`
|
||||
object to the renderer process in a `versions` global variable.
|
||||
|
||||
```js title="preload.js"
|
||||
const { contextBridge } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('versions', {
|
||||
node: () => process.versions.node,
|
||||
chrome: () => process.versions.chrome,
|
||||
electron: () => process.versions.electron,
|
||||
// we can also expose variables, not just functions
|
||||
})
|
||||
```
|
||||
|
||||
To attach this script to your renderer process, pass its path to the
|
||||
`webPreferences.preload` option in the BrowserWindow constructor:
|
||||
|
||||
```js {8-10} title="main.js"
|
||||
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()
|
||||
})
|
||||
```
|
||||
|
||||
:::info
|
||||
|
||||
There are two Node.js concepts that are used here:
|
||||
|
||||
- The [`__dirname`][dirname] string points to the path of the currently executing script
|
||||
(in this case, your project's root folder).
|
||||
- The [`path.join`][path-join] API joins multiple path segments together, creating a
|
||||
combined path string that works across all platforms.
|
||||
|
||||
:::
|
||||
|
||||
At this point, the renderer has access to the `versions` global, so let's display that
|
||||
information in the window. This variable can be accessed via `window.versions` or simply
|
||||
`versions`. Create a `renderer.js` script that uses the [`document.getElementById`]
|
||||
DOM API to replace the displayed text for the HTML element with `info` as its `id` property.
|
||||
|
||||
```js title="renderer.js"
|
||||
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()})`
|
||||
```
|
||||
|
||||
Then, modify your `index.html` by adding a new element with `info` as its `id` property,
|
||||
and attach your `renderer.js` script:
|
||||
|
||||
```html {18,20} title="index.html"
|
||||
<!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>
|
||||
```
|
||||
|
||||
After following the above steps, your app should look something like this:
|
||||
|
||||

|
||||
|
||||
And the code should look like this:
|
||||
|
||||
```fiddle docs/fiddles/tutorial-preload
|
||||
|
||||
```
|
||||
|
||||
## Communicating between processes
|
||||
|
||||
As we have mentioned above, Electron's main and renderer process have distinct responsibilities
|
||||
and are not interchangeable. This means it is not possible to access the Node.js APIs directly
|
||||
from the renderer process, nor the HTML Document Object Model (DOM) from the main process.
|
||||
|
||||
The solution for this problem is to use Electron's `ipcMain` and `ipcRenderer` modules for
|
||||
inter-process communication (IPC). To send a message from your web page to the main process,
|
||||
you can set up a main process handler with `ipcMain.handle` and
|
||||
then expose a function that calls `ipcRenderer.invoke` to trigger the handler in your preload script.
|
||||
|
||||
To illustrate, we will add a global function to the renderer called `ping()`
|
||||
that will return a string from the main process.
|
||||
|
||||
First, set up the `invoke` call in your preload script:
|
||||
|
||||
```js {1,7} title="preload.js"
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('versions', {
|
||||
node: () => process.versions.node,
|
||||
chrome: () => process.versions.chrome,
|
||||
electron: () => process.versions.electron,
|
||||
ping: () => ipcRenderer.invoke('ping'),
|
||||
// we can also expose variables, not just functions
|
||||
})
|
||||
```
|
||||
|
||||
:::caution IPC security
|
||||
|
||||
Notice how we wrap the `ipcRenderer.invoke('ping')` call in a helper function rather
|
||||
than expose the `ipcRenderer` module directly via context bridge. You **never** want to
|
||||
directly expose the entire `ipcRenderer` module via preload. This would give your renderer
|
||||
the ability to send arbitrary IPC messages to the main process, which becomes a powerful
|
||||
attack vector for malicious code.
|
||||
|
||||
:::
|
||||
|
||||
Then, set up your `handle` listener in the main process. We do this _before_
|
||||
loading the HTML file so that the handler is guaranteed to be ready before
|
||||
you send out the `invoke` call from the renderer.
|
||||
|
||||
```js {1,11} title="main.js"
|
||||
const { ipcMain } = require('electron')
|
||||
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
},
|
||||
})
|
||||
ipcMain.handle('ping', () => 'pong')
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
```
|
||||
|
||||
Once you have the sender and receiver set up, you can now send messages from the renderer
|
||||
to the main process through the `'ping'` channel you just defined.
|
||||
|
||||
```js title='renderer.js'
|
||||
const func = async () => {
|
||||
const response = await window.versions.ping()
|
||||
console.log(response) // prints out 'pong'
|
||||
}
|
||||
|
||||
func()
|
||||
```
|
||||
|
||||
:::info
|
||||
|
||||
For more in-depth explanations on using the `ipcRenderer` and `ipcMain` modules,
|
||||
check out the full [Inter-Process Communication][ipc] guide.
|
||||
|
||||
:::
|
||||
|
||||
## Summary
|
||||
|
||||
A preload script contains code that runs before your web page is loaded into the browser
|
||||
window. It has access to both DOM APIs and Node.js environment, and is often used to
|
||||
expose privileged APIs to the renderer via the `contextBridge` API.
|
||||
|
||||
Because the main and renderer processes have very different responsibilities, Electron
|
||||
apps often use the preload script to set up inter-process communication (IPC) interfaces
|
||||
to pass arbitrary messages between the two kinds of processes.
|
||||
|
||||
In the next part of the tutorial, we will be showing you resources on adding more
|
||||
functionality to your app, then teaching you distributing your app to users.
|
||||
|
||||
<!-- Links -->
|
||||
|
||||
[advanced-installation]: ./installation.md
|
||||
[application debugging]: ./application-debugging.md
|
||||
[app]: ../api/app.md
|
||||
[app-ready]: ../api/app.md#event-ready
|
||||
[app-when-ready]: ../api/app.md#appwhenready
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[commonjs]: https://nodejs.org/docs/latest/api/modules.html#modules_modules_commonjs_modules
|
||||
[compound task]: https://code.visualstudio.com/Docs/editor/tasks#_compound-tasks
|
||||
[content-script]: https://developer.chrome.com/docs/extensions/mv3/content_scripts/
|
||||
[contextbridge]: ../api/context-bridge.md
|
||||
[context-isolation]: ./context-isolation.md
|
||||
[`document.getelementbyid`]: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById
|
||||
[devtools-extension]: ./devtools-extension.md
|
||||
[dirname]: https://nodejs.org/api/modules.html#modules_dirname
|
||||
[global]: https://developer.mozilla.org/en-US/docs/Glossary/Global_object
|
||||
[ipc]: ./ipc.md
|
||||
[mdn-csp]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
|
||||
[modules]: ../api/app.md
|
||||
[node-api]: https://nodejs.org/dist/latest/docs/api/
|
||||
[package-json-main]: https://docs.npmjs.com/cli/v7/configuring-npm/package-json#main
|
||||
[package-scripts]: https://docs.npmjs.com/cli/v7/using-npm/scripts
|
||||
[path-join]: https://nodejs.org/api/path.html#path_path_join_paths
|
||||
[process-model]: ./process-model.md
|
||||
[react]: https://reactjs.org
|
||||
[sandbox]: ./sandbox.md
|
||||
[webpack]: https://webpack.js.org
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
[prerequisites]: tutorial-1-prerequisites.md
|
||||
[building your first app]: tutorial-2-first-app.md
|
||||
[preload]: tutorial-3-preload.md
|
||||
[features]: tutorial-4-adding-features.md
|
||||
[packaging]: tutorial-5-packaging.md
|
||||
[updates]: tutorial-6-publishing-updating.md
|
||||
@@ -1,77 +0,0 @@
|
||||
---
|
||||
title: 'Adding Features'
|
||||
description: 'In this step of the tutorial, we will share some resources you should read to add features to your application'
|
||||
slug: tutorial-adding-features
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
:::info Follow along the tutorial
|
||||
|
||||
This is **part 4** of the Electron tutorial.
|
||||
|
||||
1. [Prerequisites][prerequisites]
|
||||
1. [Building your First App][building your first app]
|
||||
1. [Using Preload Scripts][preload]
|
||||
1. **[Adding Features][features]**
|
||||
1. [Packaging Your Application][packaging]
|
||||
1. [Publishing and Updating][updates]
|
||||
|
||||
:::
|
||||
|
||||
## Adding application complexity
|
||||
|
||||
If you have been following along, you should have a functional Electron application
|
||||
with a static user interface. From this starting point, you can generally progress
|
||||
in developing your app in two broad directions:
|
||||
|
||||
1. Adding complexity to your renderer process' web app code
|
||||
1. Deeper integrations with the operating system and Node.js
|
||||
|
||||
It is important to understand the distinction between these two broad concepts. For the
|
||||
first point, Electron-specific resources are not necessary. Building a pretty to-do
|
||||
list in Electron is just pointing your Electron BrowserWindow to a pretty
|
||||
to-do list web app. Ultimately, you are building your renderer's UI using the same tools
|
||||
(HTML, CSS, JavaScript) that you would on the web. Therefore, Electron's docs will
|
||||
not go in-depth on how to use standard web tools.
|
||||
|
||||
On the other hand, Electron also provides a rich set of tools that allow
|
||||
you to integrate with the desktop environment, from creating tray icons to adding
|
||||
global shortcuts to displaying native menus. It also gives you all the power of a
|
||||
Node.js environment in the main process. This set of capabilities separates
|
||||
Electron applications from running a website in a browser tab, and are the
|
||||
focus of Electron's documentation.
|
||||
|
||||
## How-to examples
|
||||
|
||||
Electron's documentation has many tutorials to help you with more advanced topics
|
||||
and deeper operating system integrations. To get started, check out the
|
||||
[How-To Examples][how-to] doc.
|
||||
|
||||
:::note Let us know if something is missing!
|
||||
|
||||
If you can't find what you are looking for, please let us know on [GitHub] or in
|
||||
our [Discord server][discord]!
|
||||
|
||||
:::
|
||||
|
||||
## What's next?
|
||||
|
||||
For the rest of the tutorial, we will be shifting away from application code
|
||||
and giving you a look at how you can get your app from your developer machine
|
||||
into end users' hands.
|
||||
|
||||
<!-- Link labels -->
|
||||
|
||||
[discord]: https://discord.gg/electronjs
|
||||
[github]: https://github.com/electron/electronjs.org-new/issues/new
|
||||
[how-to]: ./examples.md
|
||||
[node-platform]: https://nodejs.org/api/process.html#process_process_platform
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
[prerequisites]: tutorial-1-prerequisites.md
|
||||
[building your first app]: tutorial-2-first-app.md
|
||||
[preload]: tutorial-3-preload.md
|
||||
[features]: tutorial-4-adding-features.md
|
||||
[packaging]: tutorial-5-packaging.md
|
||||
[updates]: tutorial-6-publishing-updating.md
|
||||
@@ -1,225 +0,0 @@
|
||||
---
|
||||
title: 'Packaging Your Application'
|
||||
description: 'To distribute your app with Electron, you need to package it and create installers.'
|
||||
slug: tutorial-packaging
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
:::info Follow along the tutorial
|
||||
|
||||
This is **part 5** of the Electron tutorial.
|
||||
|
||||
1. [Prerequisites][prerequisites]
|
||||
1. [Building your First App][building your first app]
|
||||
1. [Using Preload Scripts][preload]
|
||||
1. [Adding Features][features]
|
||||
1. **[Packaging Your Application][packaging]**
|
||||
1. [Publishing and Updating][updates]
|
||||
|
||||
:::
|
||||
|
||||
## Learning goals
|
||||
|
||||
In this part of the tutorial, we'll be going over the basics of packaging and distributing
|
||||
your app with [Electron Forge].
|
||||
|
||||
## Using Electron Forge
|
||||
|
||||
Electron does not have any tooling for packaging and distribution bundled into its core
|
||||
modules. Once you have a working Electron app in dev mode, you need to use
|
||||
additional tooling to create a packaged app you can distribute to your users (also known
|
||||
as a **distributable**). Distributables can be either installers (e.g. MSI on Windows) or
|
||||
portable executable files (e.g. `.app` on macOS).
|
||||
|
||||
Electron Forge is an all-in-one tool that handles the packaging and distribution of Electron
|
||||
apps. Under the hood, it combines a lot of existing Electron tools (e.g. [`electron-packager`],
|
||||
[`@electron/osx-sign`], [`electron-winstaller`], etc.) into a single interface so you do not
|
||||
have to worry about wiring them all together.
|
||||
|
||||
### Importing your project into Forge
|
||||
|
||||
You can install Electron Forge's CLI in your project's `devDependencies` and import your
|
||||
existing project with a handy conversion script.
|
||||
|
||||
```sh npm2yarn
|
||||
npm install --save-dev @electron-forge/cli
|
||||
npx electron-forge import
|
||||
```
|
||||
|
||||
Once the conversion script is done, Forge should have added a few scripts
|
||||
to your `package.json` file.
|
||||
|
||||
```json title='package.json'
|
||||
//...
|
||||
"scripts": {
|
||||
"start": "electron-forge start",
|
||||
"package": "electron-forge package",
|
||||
"make": "electron-forge make"
|
||||
},
|
||||
//...
|
||||
```
|
||||
|
||||
:::info CLI documentation
|
||||
|
||||
For more information on `make` and other Forge APIs, check out
|
||||
the [Electron Forge CLI documentation].
|
||||
|
||||
:::
|
||||
|
||||
You should also notice that your package.json now has a few more packages installed
|
||||
under your `devDependencies`, and contains an added `config.forge` field with an array
|
||||
of makers configured. **Makers** are Forge plugins that create distributables from
|
||||
your source code. You should see multiple makers in the pre-populated configuration,
|
||||
one for each target platform.
|
||||
|
||||
### Creating a distributable
|
||||
|
||||
To create a distributable, use your project's new `make` script, which runs the
|
||||
`electron-forge make` command.
|
||||
|
||||
```sh npm2yarn
|
||||
npm run make
|
||||
```
|
||||
|
||||
This `make` command contains two steps:
|
||||
|
||||
1. It will first run `electron-forge package` under the hood, which bundles your app
|
||||
code together with the Electron binary. The packaged code is generated into a folder.
|
||||
1. It will then use this packaged app folder to create a separate distributable for each
|
||||
configured maker.
|
||||
|
||||
After the script runs, you should see an `out` folder containing both the distributable
|
||||
and a folder containing the packaged application code.
|
||||
|
||||
```plain title='macOS output example'
|
||||
out/
|
||||
├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
|
||||
├── ...
|
||||
└── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app
|
||||
```
|
||||
|
||||
The distributable in the `out/make` folder should be ready to launch! You have now
|
||||
created your first bundled Electron application.
|
||||
|
||||
:::tip Distributable formats
|
||||
|
||||
Electron Forge can be configured to create distributables in different OS-specific formats
|
||||
(e.g. DMG, deb, MSI, etc.). See Forge's [Makers] documentation for all configuration options.
|
||||
|
||||
:::
|
||||
|
||||
:::note Packaging without Electron Forge
|
||||
|
||||
If you want to manually package your code, or if you're just interested understanding the
|
||||
mechanics behind packaging an Electron app, check out the full [Application Packaging]
|
||||
documentation.
|
||||
|
||||
:::
|
||||
|
||||
## Important: signing your code
|
||||
|
||||
In order to distribute desktop applications to end users, we _highly recommended_ for you
|
||||
to **code sign** your Electron app. Code signing is an important part of shipping
|
||||
desktop applications, and is mandatory for the auto-update step in the final part
|
||||
of the tutorial.
|
||||
|
||||
Code signing is a security technology that you use to certify that a desktop app was
|
||||
created by a known source. Windows and macOS have their own OS-specific code signing
|
||||
systems that will make it difficult for users to download or launch unsigned applications.
|
||||
|
||||
If you already have code signing certificates for Windows and macOS, you can set your
|
||||
credentials in your Forge configuration. Otherwise, please refer to the full
|
||||
[Code Signing] documentation to learn how to purchase a certificate and for more information
|
||||
on the desktop app code signing process.
|
||||
|
||||
On macOS, code signing is done at the app packaging level. On Windows, distributable installers
|
||||
are signed instead.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="macos" label="macOS" default>
|
||||
|
||||
```json title='package.json' {6-18}
|
||||
{
|
||||
//...
|
||||
"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": "this-is-a-secret"
|
||||
}
|
||||
}
|
||||
//...
|
||||
}
|
||||
}
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="windows" label="Windows">
|
||||
|
||||
```json title='package.json' {6-14}
|
||||
{
|
||||
//...
|
||||
"config": {
|
||||
"forge": {
|
||||
//...
|
||||
"makers": [
|
||||
{
|
||||
"name": "@electron-forge/maker-squirrel",
|
||||
"config": {
|
||||
"certificateFile": "./cert.pfx",
|
||||
"certificatePassword": "this-is-a-secret"
|
||||
}
|
||||
}
|
||||
]
|
||||
//...
|
||||
}
|
||||
}
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Summary
|
||||
|
||||
Electron applications need to be packaged to be distributed to users. In this tutorial,
|
||||
you imported your app into Electron Forge and configured it to package your app and
|
||||
generate installers.
|
||||
|
||||
In order for your application to be trusted by the user's system, you need to digitally
|
||||
certify that the distributable is authentic and untampered by code signing it. Your app
|
||||
can be signed through Forge once you configure it to use your code signing certificate
|
||||
information.
|
||||
|
||||
[`@electron/osx-sign`]: https://github.com/electron/osx-sign
|
||||
[application packaging]: ./application-distribution.md
|
||||
[code signing]: ./code-signing.md
|
||||
[`electron-packager`]: https://github.com/electron/electron-packager
|
||||
[`electron-winstaller`]: https://github.com/electron/windows-installer
|
||||
[electron forge]: https://www.electronforge.io
|
||||
[electron forge cli documentation]: https://www.electronforge.io/cli#commands
|
||||
[makers]: https://www.electronforge.io/config/makers
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
[prerequisites]: tutorial-1-prerequisites.md
|
||||
[building your first app]: tutorial-2-first-app.md
|
||||
[preload]: tutorial-3-preload.md
|
||||
[features]: tutorial-4-adding-features.md
|
||||
[packaging]: tutorial-5-packaging.md
|
||||
[updates]: tutorial-6-publishing-updating.md
|
||||
@@ -1,251 +0,0 @@
|
||||
---
|
||||
title: 'Publishing and Updating'
|
||||
description: "There are several ways to update an Electron application. The easiest and officially supported one is taking advantage of the built-in Squirrel framework and Electron's autoUpdater module."
|
||||
slug: tutorial-publishing-updating
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
:::info Follow along the tutorial
|
||||
|
||||
This is **part 6** of the Electron tutorial.
|
||||
|
||||
1. [Prerequisites][prerequisites]
|
||||
1. [Building your First App][building your first app]
|
||||
1. [Using Preload Scripts][preload]
|
||||
1. [Adding Features][features]
|
||||
1. [Packaging Your Application][packaging]
|
||||
1. **[Publishing and Updating][updates]**
|
||||
|
||||
:::
|
||||
|
||||
## Learning goals
|
||||
|
||||
If you've been following along, this is the last step of the tutorial! In this part,
|
||||
you will publish your app to GitHub releases and integrate automatic updates
|
||||
into your app code.
|
||||
|
||||
## Using update.electronjs.org
|
||||
|
||||
The Electron maintainers provide a free auto-updating service for open-source apps
|
||||
at [https://update.electronjs.org](https://update.electronjs.org). Its requirements are:
|
||||
|
||||
- Your app runs on macOS or Windows
|
||||
- Your app has a public GitHub repository
|
||||
- Builds are published to [GitHub releases]
|
||||
- Builds are [code signed][code-signed]
|
||||
|
||||
At this point, we'll assume that you have already pushed all your
|
||||
code to a public GitHub repository.
|
||||
|
||||
:::info Alternative update services
|
||||
|
||||
If you're using an alternate repository host (e.g. GitLab or Bitbucket) or if
|
||||
you need to keep your code repository private, please refer to our
|
||||
[step-by-step guide][update-server] on hosting your own Electron update server.
|
||||
|
||||
:::
|
||||
|
||||
## Publishing a GitHub release
|
||||
|
||||
Electron Forge has [Publisher] plugins that can automate the distribution
|
||||
of your packaged application to various sources. In this tutorial, we will
|
||||
be using the GitHub Publisher, which will allow us to publish
|
||||
our code to GitHub releases.
|
||||
|
||||
### Generating a personal access token
|
||||
|
||||
Forge cannot publish to any repository on GitHub without permission. You
|
||||
need to pass in an authenticated token that gives Forge access to
|
||||
your GitHub releases. The easiest way to do this is to
|
||||
[create a new personal access token (PAT)][new-pat]
|
||||
with the `public_repo` scope, which gives write access to your public repositories.
|
||||
**Make sure to keep this token a secret.**
|
||||
|
||||
### Setting up the GitHub Publisher
|
||||
|
||||
#### Installing the module
|
||||
|
||||
Forge's [GitHub Publisher] is a plugin that
|
||||
needs to be installed in your project's `devDependencies`:
|
||||
|
||||
```sh npm2yarn
|
||||
npm install --save-dev @electron-forge/publisher-github
|
||||
```
|
||||
|
||||
#### Configuring the publisher in Forge
|
||||
|
||||
Once you have it installed, you need to set it up in your Forge
|
||||
configuration. A full list of options is documented in the Forge's
|
||||
[`PublisherGitHubConfig`] API docs.
|
||||
|
||||
```json title='package.json' {6-16}
|
||||
{
|
||||
//...
|
||||
"config": {
|
||||
"forge": {
|
||||
"publishers": [
|
||||
{
|
||||
"name": "@electron-forge/publisher-github",
|
||||
"config": {
|
||||
"repository": {
|
||||
"owner": "github-user-name",
|
||||
"name": "github-repo-name"
|
||||
},
|
||||
"prerelease": false,
|
||||
"draft": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
:::tip Drafting releases before publishing
|
||||
|
||||
Notice that you have configured Forge to publish your release as a draft.
|
||||
This will allow you to see the release with its generated artifacts
|
||||
without actually publishing it to your end users. You can manually
|
||||
publish your releases via GitHub after writing release notes and
|
||||
double-checking that your distributables work.
|
||||
|
||||
:::
|
||||
|
||||
#### Setting up your authentication token
|
||||
|
||||
You also need to make the Publisher aware of your authentication token.
|
||||
By default, it will use the value stored in the `GITHUB_TOKEN` environment
|
||||
variable.
|
||||
|
||||
### Running the publish command
|
||||
|
||||
Add Forge's [publish command] to your npm scripts.
|
||||
|
||||
```json {6} title='package.json'
|
||||
//...
|
||||
"scripts": {
|
||||
"start": "electron-forge start",
|
||||
"package": "electron-forge package",
|
||||
"make": "electron-forge make",
|
||||
"publish": "electron-forge publish"
|
||||
},
|
||||
//...
|
||||
```
|
||||
|
||||
This command will run your configured makers and publish the output distributables to a new
|
||||
GitHub release.
|
||||
|
||||
```sh npm2yarn
|
||||
npm run publish
|
||||
```
|
||||
|
||||
By default, this will only publish a single distributable for your host operating system and
|
||||
architecture. You can publish for different architectures by passing in the `--arch` flag to your
|
||||
Forge commands.
|
||||
|
||||
The name of this release will correspond to the `version` field in your project's package.json file.
|
||||
|
||||
:::tip Tagging releases
|
||||
|
||||
Optionally, you can also [tag your releases in Git][git-tag] so that your
|
||||
release is associated with a labeled point in your code history. npm comes
|
||||
with a handy [`npm version`](https://docs.npmjs.com/cli/v8/commands/npm-version)
|
||||
command that can handle the version bumping and tagging for you.
|
||||
|
||||
:::
|
||||
|
||||
#### Bonus: Publishing in GitHub Actions
|
||||
|
||||
Publishing locally can be painful, especially because you can only create distributables
|
||||
for your host operating system (i.e. you can't publish a Window `.exe` file from macOS).
|
||||
|
||||
A solution for this would be to publish your app via automation workflows
|
||||
such as [GitHub Actions], which can run tasks in the
|
||||
cloud on Ubuntu, macOS, and Windows. This is the exact approach taken by [Electron Fiddle].
|
||||
You can refer to Fiddle's [Build and Release pipeline][fiddle-build]
|
||||
and [Forge configuration][fiddle-forge-config]
|
||||
for more details.
|
||||
|
||||
## Instrumenting your updater code
|
||||
|
||||
Now that we have a functional release system via GitHub releases, we now need to tell our
|
||||
Electron app to download an update whenever a new release is out. Electron apps do this
|
||||
via the [autoUpdater] module, which reads from an update server feed to check if a new version
|
||||
is available for download.
|
||||
|
||||
The update.electronjs.org service provides an updater-compatible feed. For example, Electron
|
||||
Fiddle v0.28.0 will check the endpoint at https://update.electronjs.org/electron/fiddle/darwin/v0.28.0
|
||||
to see if a newer GitHub release is available.
|
||||
|
||||
After your release is published to GitHub, the update.electronjs.org service should work
|
||||
for your application. The only step left is to configure the feed with the autoUpdater module.
|
||||
|
||||
To make this process easier, the Electron team maintains the [`update-electron-app`] module,
|
||||
which sets up the autoUpdater boilerplate for update.electronjs.org in one function
|
||||
call — no configuration required. This module will search for the update.electronjs.org
|
||||
feed that matches your project's package.json `"repository"` field.
|
||||
|
||||
First, install the module as a runtime dependency.
|
||||
|
||||
```sh npm2yarn
|
||||
npm install update-electron-app
|
||||
```
|
||||
|
||||
Then, import the module and call it immediately in the main process.
|
||||
|
||||
```js title='main.js'
|
||||
require('update-electron-app')()
|
||||
```
|
||||
|
||||
And that is all it takes! Once your application is packaged, it will update itself for each new
|
||||
GitHub release that you publish.
|
||||
|
||||
## Summary
|
||||
|
||||
In this tutorial, we configured Electron Forge's GitHub Publisher to upload your app's
|
||||
distributables to GitHub releases. Since distributables cannot always be generated
|
||||
between platforms, we recommend setting up your building and publishing flow
|
||||
in a Continuous Integration pipeline if you do not have access to machines.
|
||||
|
||||
Electron applications can self-update by pointing the autoUpdater module to an update server feed.
|
||||
update.electronjs.org is a free update server provided by Electron for open-source applications
|
||||
published on GitHub releases. Configuring your Electron app to use this service is as easy as
|
||||
installing and importing the `update-electron-app` module.
|
||||
|
||||
If your application is not eligible for update.electronjs.org, you should instead deploy your
|
||||
own update server and configure the autoUpdater module yourself.
|
||||
|
||||
:::info 🌟 You're done!
|
||||
|
||||
From here, you have officially completed our tutorial to Electron. Feel free to explore the
|
||||
rest of our docs and happy developing! If you have questions, please stop by our community
|
||||
[Discord server].
|
||||
|
||||
:::
|
||||
|
||||
[autoupdater]: ../api/auto-updater.md
|
||||
[code-signed]: ./code-signing.md
|
||||
[discord server]: https://discord.gg/electronjs
|
||||
[electron fiddle]: https://electronjs.org/fiddle
|
||||
[fiddle-build]: https://github.com/electron/fiddle/blob/master/.github/workflows/build.yaml
|
||||
[fiddle-forge-config]: https://github.com/electron/fiddle/blob/master/forge.config.js
|
||||
[github actions]: https://github.com/features/actions
|
||||
[github publisher]: https://www.electronforge.io/config/publishers/github
|
||||
[github releases]: https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository
|
||||
[git tag]: https://git-scm.com/book/en/v2/Git-Basics-Tagging
|
||||
[new-pat]: https://github.com/settings/tokens/new
|
||||
[publish command]: https://www.electronforge.io/cli#publish
|
||||
[publisher]: https://www.electronforge.io/config/publishers
|
||||
[`publishergithubconfig`]: https://js.electronforge.io/publisher/github/interfaces/publishergithubconfig
|
||||
[`update-electron-app`]: https://github.com/electron/update-electron-app
|
||||
[update-server]: ./updates.md
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
[prerequisites]: tutorial-1-prerequisites.md
|
||||
[building your first app]: tutorial-2-first-app.md
|
||||
[preload]: tutorial-3-preload.md
|
||||
[features]: tutorial-4-adding-features.md
|
||||
[packaging]: tutorial-5-packaging.md
|
||||
[updates]: tutorial-6-publishing-updating.md
|
||||
@@ -1,16 +1,11 @@
|
||||
---
|
||||
title: 'Updating Applications'
|
||||
description: "There are several ways to update an Electron application. The easiest and officially supported one is taking advantage of the built-in Squirrel framework and Electron's autoUpdater module."
|
||||
slug: updates
|
||||
hide_title: false
|
||||
---
|
||||
# Updating Applications
|
||||
|
||||
There are several ways to provide automatic updates to your Electron application.
|
||||
The easiest and officially supported one is taking advantage of the built-in
|
||||
There are several ways to update an Electron application. The easiest and
|
||||
officially supported one is taking advantage of the built-in
|
||||
[Squirrel](https://github.com/Squirrel) framework and
|
||||
Electron's [autoUpdater](../api/auto-updater.md) module.
|
||||
|
||||
## Using update.electronjs.org
|
||||
## Using `update.electronjs.org`
|
||||
|
||||
The Electron team maintains [update.electronjs.org], a free and open-source
|
||||
webservice that Electron apps can use to self-update. The service is designed
|
||||
@@ -18,77 +13,72 @@ for Electron apps that meet the following criteria:
|
||||
|
||||
- App runs on macOS or Windows
|
||||
- App has a public GitHub repository
|
||||
- Builds are published to [GitHub Releases][gh-releases]
|
||||
- Builds are [code-signed](./code-signing.md)
|
||||
- Builds are published to GitHub Releases
|
||||
- Builds are code-signed
|
||||
|
||||
The easiest way to use this service is by installing [update-electron-app],
|
||||
a Node.js module preconfigured for use with update.electronjs.org.
|
||||
|
||||
Install the module using your Node.js package manager of choice:
|
||||
Install the module:
|
||||
|
||||
```sh npm2yarn
|
||||
```sh
|
||||
npm install update-electron-app
|
||||
```
|
||||
|
||||
Then, invoke the updater from your app's main process file:
|
||||
Invoke the updater from your app's main process file:
|
||||
|
||||
```js title="main.js"
|
||||
```js
|
||||
require('update-electron-app')()
|
||||
```
|
||||
|
||||
By default, this module will check for updates at app startup, then every ten
|
||||
minutes. When an update is found, it will automatically be downloaded in the background.
|
||||
When the download completes, a dialog is displayed allowing the user to restart the app.
|
||||
minutes. When an update is found, it will automatically be downloaded in the background. When the download completes, a dialog is displayed allowing the user
|
||||
to restart the app.
|
||||
|
||||
If you need to customize your configuration, you can
|
||||
[pass options to update-electron-app][update-electron-app]
|
||||
[pass options to `update-electron-app`][update-electron-app]
|
||||
or
|
||||
[use the update service directly][update.electronjs.org].
|
||||
|
||||
## Using other update services
|
||||
## Deploying an Update Server
|
||||
|
||||
If you're developing a private Electron application, or if you're not
|
||||
publishing releases to GitHub Releases, it may be necessary to run your own
|
||||
update server.
|
||||
|
||||
### Step 1: Deploying an update server
|
||||
|
||||
Depending on your needs, you can choose from one of these:
|
||||
|
||||
- [Hazel][hazel] – Update server for private or open-source apps which can be
|
||||
deployed for free on [Vercel][vercel]. It pulls from [GitHub Releases][gh-releases]
|
||||
and leverages the power of GitHub's CDN.
|
||||
deployed for free on [Vercel][vercel]. It pulls from [GitHub Releases][gh-releases]
|
||||
and leverages the power of GitHub's CDN.
|
||||
- [Nuts][nuts] – Also uses [GitHub Releases][gh-releases], but caches app
|
||||
updates on disk and supports private repositories.
|
||||
updates on disk and supports private repositories.
|
||||
- [electron-release-server][electron-release-server] – Provides a dashboard for
|
||||
handling releases and does not require releases to originate on GitHub.
|
||||
handling releases and does not require releases to originate on GitHub.
|
||||
- [Nucleus][nucleus] – A complete update server for Electron apps maintained by
|
||||
Atlassian. Supports multiple applications and channels; uses a static file store
|
||||
to minify server cost.
|
||||
Atlassian. Supports multiple applications and channels; uses a static file store
|
||||
to minify server cost.
|
||||
|
||||
Once you've deployed your update server, you can instrument your app code to receive and
|
||||
apply the updates with Electron's [autoUpdater] module.
|
||||
## Implementing Updates in Your App
|
||||
|
||||
### Step 2: Receiving updates in your app
|
||||
Once you've deployed your update server, continue with importing the required
|
||||
modules in your code. The following code might vary for different server
|
||||
software, but it works like described when using
|
||||
[Hazel][hazel].
|
||||
|
||||
First, import the required modules in your main process code. The following code might
|
||||
vary for different server software, but it works like described when using [Hazel][hazel].
|
||||
**Important:** Please ensure that the code below will only be executed in
|
||||
your packaged app, and not in development. You can use
|
||||
[electron-is-dev](https://github.com/sindresorhus/electron-is-dev) to check for
|
||||
the environment.
|
||||
|
||||
:::warning Check your execution environment!
|
||||
|
||||
Please ensure that the code below will only be executed in your packaged app, and not in development.
|
||||
You can use the [app.isPackaged](../api/app.md#appispackaged-readonly) API to check the environment.
|
||||
|
||||
:::
|
||||
|
||||
```javascript title='main.js'
|
||||
```javascript
|
||||
const { app, autoUpdater, dialog } = require('electron')
|
||||
```
|
||||
|
||||
Next, construct the URL of the update server feed and tell
|
||||
Next, construct the URL of the update server and tell
|
||||
[autoUpdater](../api/auto-updater.md) about it:
|
||||
|
||||
```javascript title='main.js'
|
||||
```javascript
|
||||
const server = 'https://your-deployment-url.com'
|
||||
const url = `${server}/update/${process.platform}/${app.getVersion()}`
|
||||
|
||||
@@ -97,32 +87,32 @@ autoUpdater.setFeedURL({ url })
|
||||
|
||||
As the final step, check for updates. The example below will check every minute:
|
||||
|
||||
```javascript title='main.js'
|
||||
```javascript
|
||||
setInterval(() => {
|
||||
autoUpdater.checkForUpdates()
|
||||
}, 60000)
|
||||
```
|
||||
|
||||
Once your application is [packaged](./application-distribution.md),
|
||||
Once your application is [packaged](../tutorial/application-distribution.md),
|
||||
it will receive an update for each new
|
||||
[GitHub Release](https://help.github.com/articles/creating-releases/) that you
|
||||
publish.
|
||||
|
||||
### Step 3: Notifying users when updates are available
|
||||
## Applying Updates
|
||||
|
||||
Now that you've configured the basic update mechanism for your application, you
|
||||
need to ensure that the user will get notified when there's an update. This
|
||||
can be achieved using the [autoUpdater API events](../api/auto-updater.md#events):
|
||||
can be achieved using the autoUpdater API
|
||||
[events](../api/auto-updater.md#events):
|
||||
|
||||
```javascript title="main.js"
|
||||
```javascript
|
||||
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
|
||||
const dialogOpts = {
|
||||
type: 'info',
|
||||
buttons: ['Restart', 'Later'],
|
||||
title: 'Application Update',
|
||||
message: process.platform === 'win32' ? releaseNotes : releaseName,
|
||||
detail:
|
||||
'A new version has been downloaded. Restart the application to apply the updates.',
|
||||
detail: 'A new version has been downloaded. Restart the application to apply the updates.'
|
||||
}
|
||||
|
||||
dialog.showMessageBox(dialogOpts).then((returnValue) => {
|
||||
@@ -135,22 +125,16 @@ Also make sure that errors are
|
||||
[being handled](../api/auto-updater.md#event-error). Here's an example
|
||||
for logging them to `stderr`:
|
||||
|
||||
```javascript title="main.js"
|
||||
autoUpdater.on('error', (message) => {
|
||||
```javascript
|
||||
autoUpdater.on('error', message => {
|
||||
console.error('There was a problem updating the application')
|
||||
console.error(message)
|
||||
})
|
||||
```
|
||||
|
||||
:::info Handling updates manually
|
||||
## Handling Updates Manually
|
||||
|
||||
Because the requests made by autoUpdate aren't under your direct control, you may find situations
|
||||
that are difficult to handle (such as if the update server is behind authentication). The `url`
|
||||
field supports the `file://` protocol, which means that with some effort, you can sidestep the
|
||||
server-communication aspect of the process by loading your update from a local directory.
|
||||
[Here's an example of how this could work](https://github.com/electron/electron/issues/5020#issuecomment-477636990).
|
||||
|
||||
:::
|
||||
Because the requests made by Auto Update aren't under your direct control, you may find situations that are difficult to handle (such as if the update server is behind authentication). The `url` field does support files, which means that with some effort, you can sidestep the server-communication aspect of the process. [Here's an example of how this could work](https://github.com/electron/electron/issues/5020#issuecomment-477636990).
|
||||
|
||||
[vercel]: https://vercel.com
|
||||
[hazel]: https://github.com/vercel/hazel
|
||||
|
||||
@@ -115,7 +115,7 @@ const win = new BrowserWindow({
|
||||
})
|
||||
```
|
||||
|
||||
On either platform `titleBarOverlay` can also be an object. On both macOS and Windows, the height of the overlay can be specified with the `height` property. On Windows, the color of the overlay and its symbols can be specified using the `color` and `symbolColor` properties respectively.
|
||||
On Windows, you can also specify additional parameters. The color of the overlay and its symbols can be specified by setting `titleBarOverlay` to an object and using the `color` and `symbolColor` properties respectively. The height of the overlay can also be specified with the `height` property.
|
||||
|
||||
If a color option is not specified, the color will default to its system color for the window control buttons. Similarly, if the height option is not specified it will default to the default height:
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ auto_filenames = {
|
||||
"docs/api/power-save-blocker.md",
|
||||
"docs/api/process.md",
|
||||
"docs/api/protocol.md",
|
||||
"docs/api/push-notifications.md",
|
||||
"docs/api/safe-storage.md",
|
||||
"docs/api/screen.md",
|
||||
"docs/api/service-workers.md",
|
||||
@@ -213,7 +212,6 @@ auto_filenames = {
|
||||
"lib/browser/api/power-monitor.ts",
|
||||
"lib/browser/api/power-save-blocker.ts",
|
||||
"lib/browser/api/protocol.ts",
|
||||
"lib/browser/api/push-notifications.ts",
|
||||
"lib/browser/api/safe-storage.ts",
|
||||
"lib/browser/api/screen.ts",
|
||||
"lib/browser/api/session.ts",
|
||||
|
||||
@@ -23,7 +23,6 @@ filenames = {
|
||||
|
||||
lib_sources_linux = [
|
||||
"shell/browser/browser_linux.cc",
|
||||
"shell/browser/electron_browser_main_parts_linux.cc",
|
||||
"shell/browser/lib/power_observer_linux.cc",
|
||||
"shell/browser/lib/power_observer_linux.h",
|
||||
"shell/browser/linux/unity_service.cc",
|
||||
@@ -86,8 +85,6 @@ filenames = {
|
||||
"shell/browser/ui/message_box_win.cc",
|
||||
"shell/browser/ui/tray_icon_win.cc",
|
||||
"shell/browser/ui/views/electron_views_delegate_win.cc",
|
||||
"shell/browser/ui/views/win_icon_painter.cc",
|
||||
"shell/browser/ui/views/win_icon_painter.h",
|
||||
"shell/browser/ui/views/win_frame_view.cc",
|
||||
"shell/browser/ui/views/win_frame_view.h",
|
||||
"shell/browser/ui/views/win_caption_button.cc",
|
||||
@@ -129,7 +126,6 @@ filenames = {
|
||||
"shell/browser/api/electron_api_menu_mac.mm",
|
||||
"shell/browser/api/electron_api_native_theme_mac.mm",
|
||||
"shell/browser/api/electron_api_power_monitor_mac.mm",
|
||||
"shell/browser/api/electron_api_push_notifications_mac.mm",
|
||||
"shell/browser/api/electron_api_system_preferences_mac.mm",
|
||||
"shell/browser/api/electron_api_web_contents_mac.mm",
|
||||
"shell/browser/auto_updater_mac.mm",
|
||||
@@ -297,8 +293,6 @@ filenames = {
|
||||
"shell/browser/api/electron_api_printing.cc",
|
||||
"shell/browser/api/electron_api_protocol.cc",
|
||||
"shell/browser/api/electron_api_protocol.h",
|
||||
"shell/browser/api/electron_api_push_notifications.cc",
|
||||
"shell/browser/api/electron_api_push_notifications.h",
|
||||
"shell/browser/api/electron_api_safe_storage.cc",
|
||||
"shell/browser/api/electron_api_safe_storage.h",
|
||||
"shell/browser/api/electron_api_screen.cc",
|
||||
@@ -416,6 +410,8 @@ filenames = {
|
||||
"shell/browser/media/media_capture_devices_dispatcher.h",
|
||||
"shell/browser/media/media_device_id_salt.cc",
|
||||
"shell/browser/media/media_device_id_salt.h",
|
||||
"shell/browser/media/media_stream_devices_controller.cc",
|
||||
"shell/browser/media/media_stream_devices_controller.h",
|
||||
"shell/browser/microtasks_runner.cc",
|
||||
"shell/browser/microtasks_runner.h",
|
||||
"shell/browser/native_browser_view.cc",
|
||||
@@ -647,6 +643,8 @@ filenames = {
|
||||
"shell/common/process_util.h",
|
||||
"shell/common/skia_util.cc",
|
||||
"shell/common/skia_util.h",
|
||||
"shell/common/v8_value_converter.cc",
|
||||
"shell/common/v8_value_converter.h",
|
||||
"shell/common/v8_value_serializer.cc",
|
||||
"shell/common/v8_value_serializer.h",
|
||||
"shell/common/world_ids.h",
|
||||
|
||||
@@ -1,376 +1,49 @@
|
||||
libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/CMakeLists.txt",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/adjacent_find.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/all_of.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/any_of.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/binary_search.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/clamp.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/comp.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/comp_ref_type.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/copy.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/copy_backward.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/copy_if.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/copy_n.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/count.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/count_if.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/equal.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/equal_range.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/fill.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/fill_n.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/find.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/find_end.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/find_first_of.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/find_if.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/find_if_not.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/for_each.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/for_each_n.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/generate.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/generate_n.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/half_positive.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/in_found_result.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/in_fun_result.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/in_in_out_result.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/in_in_result.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/in_out_out_result.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/in_out_result.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/includes.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/inplace_merge.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/is_heap.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/is_heap_until.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/is_partitioned.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/is_permutation.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/is_sorted.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/is_sorted_until.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/iter_swap.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/lexicographical_compare.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/lower_bound.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/make_heap.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/max.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/max_element.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/merge.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/min.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/min_element.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/min_max_result.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/minmax.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/minmax_element.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/mismatch.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/move.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/move_backward.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/next_permutation.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/none_of.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/nth_element.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/partial_sort.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/partial_sort_copy.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/partition.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/partition_copy.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/partition_point.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/pop_heap.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/prev_permutation.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/push_heap.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/ranges_find.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/ranges_find_if.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/ranges_find_if_not.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/ranges_max_element.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/ranges_min.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/ranges_min_element.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/ranges_mismatch.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/ranges_swap_ranges.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/remove.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/remove_copy.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/remove_copy_if.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/remove_if.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/replace.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/replace_copy.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/replace_copy_if.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/replace_if.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/reverse.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/reverse_copy.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/rotate.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/rotate_copy.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/sample.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/search.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/search_n.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/set_difference.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/set_intersection.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/set_symmetric_difference.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/set_union.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/shift_left.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/shift_right.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/shuffle.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/sift_down.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/sort.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/sort_heap.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/stable_partition.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/stable_sort.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/swap_ranges.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/transform.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/unique.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/unique_copy.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/unwrap_iter.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__algorithm/upper_bound.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__assert",
|
||||
"//buildtools/third_party/libc++/trunk/include/__availability",
|
||||
"//buildtools/third_party/libc++/trunk/include/__bit/bit_cast.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__bit/byteswap.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__bit_reference",
|
||||
"//buildtools/third_party/libc++/trunk/include/__bits",
|
||||
"//buildtools/third_party/libc++/trunk/include/__bsd_locale_defaults.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__bsd_locale_fallbacks.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__charconv/chars_format.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__charconv/from_chars_result.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__charconv/to_chars_result.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__chrono/calendar.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__chrono/convert_to_timespec.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__chrono/duration.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__chrono/file_clock.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__chrono/high_resolution_clock.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__chrono/steady_clock.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__chrono/system_clock.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__chrono/time_point.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/common_comparison_category.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/compare_partial_order_fallback.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/compare_strong_order_fallback.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/compare_three_way.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/compare_three_way_result.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/compare_weak_order_fallback.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/is_eq.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/ordering.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/partial_order.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/strong_order.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/synth_three_way.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/three_way_comparable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__compare/weak_order.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/arithmetic.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/assignable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/boolean_testable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/class_or_enum.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/common_reference_with.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/common_with.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/constructible.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/convertible_to.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/copyable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/derived_from.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/destructible.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/different_from.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/equality_comparable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/invocable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/movable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/predicate.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/regular.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/relation.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/same_as.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/semiregular.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/swappable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__concepts/totally_ordered.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__config",
|
||||
"//buildtools/third_party/libc++/trunk/include/__config_site.in",
|
||||
"//buildtools/third_party/libc++/trunk/include/__coroutine/coroutine_handle.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__coroutine/coroutine_traits.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__coroutine/noop_coroutine_handle.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__coroutine/trivial_awaitables.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__debug",
|
||||
"//buildtools/third_party/libc++/trunk/include/__errc",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/copy_options.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/directory_entry.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/directory_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/directory_options.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/file_status.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/file_time_type.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/file_type.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/filesystem_error.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/operations.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/path.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/path_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/perm_options.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/perms.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/recursive_directory_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/space_info.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/u8path.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/format_arg.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/format_args.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/format_context.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/format_error.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/format_fwd.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/format_parse_context.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/format_string.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/format_to_n_result.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/formatter.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/formatter_bool.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/formatter_char.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/formatter_floating_point.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/formatter_integer.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/formatter_integral.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/formatter_pointer.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/formatter_string.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__format/parser_std_format_spec.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/binary_function.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/binary_negate.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/bind.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/bind_back.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/bind_front.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/binder1st.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/binder2nd.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/compose.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/default_searcher.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/function.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/hash.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/identity.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/invoke.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/is_transparent.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/mem_fn.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/mem_fun_ref.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/not_fn.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/operations.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/perfect_forward.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/pointer_to_binary_function.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/pointer_to_unary_function.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/ranges_operations.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/reference_wrapper.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/unary_function.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/unary_negate.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/unwrap_ref.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional/weak_result_type.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional_03",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional_base",
|
||||
"//buildtools/third_party/libc++/trunk/include/__functional_base_03",
|
||||
"//buildtools/third_party/libc++/trunk/include/__hash_table",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ios/fpos.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/access.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/advance.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/back_insert_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/common_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/concepts.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/counted_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/data.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/default_sentinel.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/distance.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/empty.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/erase_if_container.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/front_insert_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/incrementable_traits.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/indirectly_comparable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/insert_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/istream_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/istreambuf_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/iter_move.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/iter_swap.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/iterator_traits.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/mergeable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/move_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/next.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/ostream_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/ostreambuf_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/permutable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/prev.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/projected.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/readable_traits.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/reverse_access.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/reverse_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/size.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/sortable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/unreachable_sentinel.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__iterator/wrap_iter.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__libcpp_version",
|
||||
"//buildtools/third_party/libc++/trunk/include/__locale",
|
||||
"//buildtools/third_party/libc++/trunk/include/__mbstate_t.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/addressof.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/allocation_guard.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/allocator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/allocator_arg_t.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/allocator_traits.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/auto_ptr.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/compressed_pair.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/concepts.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/construct_at.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/pointer_safety.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/pointer_traits.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/ranges_construct_at.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/ranges_uninitialized_algorithms.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/raw_storage_iterator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/shared_ptr.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/temporary_buffer.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/uninitialized_algorithms.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/unique_ptr.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/uses_allocator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/voidify.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__mutex_base",
|
||||
"//buildtools/third_party/libc++/trunk/include/__node_handle",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/accumulate.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/adjacent_difference.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/exclusive_scan.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/gcd_lcm.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/inclusive_scan.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/inner_product.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/iota.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/midpoint.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/partial_sum.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/reduce.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/transform_exclusive_scan.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/transform_inclusive_scan.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/transform_reduce.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/bernoulli_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/binomial_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/cauchy_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/chi_squared_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/clamp_to_integral.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/default_random_engine.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/discard_block_engine.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/discrete_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/exponential_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/extreme_value_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/fisher_f_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/gamma_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/generate_canonical.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/geometric_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/independent_bits_engine.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/is_seed_sequence.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/is_valid.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/knuth_b.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/linear_congruential_engine.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/log2.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/lognormal_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/mersenne_twister_engine.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/negative_binomial_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/normal_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/piecewise_constant_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/piecewise_linear_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/poisson_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/random_device.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/ranlux.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/seed_seq.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/shuffle_order_engine.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/student_t_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/subtract_with_carry_engine.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/uniform_int_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/uniform_random_bit_generator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/uniform_real_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__random/weibull_distribution.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__nullptr",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/access.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/all.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/common_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/concepts.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/copyable_box.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/counted.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/dangling.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/data.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/drop_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/empty.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/empty_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/enable_borrowed_range.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/enable_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/iota_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/join_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/non_propagating_cache.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/owning_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/range_adaptor.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/rbegin.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/ref_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/rend.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/reverse_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/single_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/size.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/subrange.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/take_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/transform_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/view_interface.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/views.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__split_buffer",
|
||||
"//buildtools/third_party/libc++/trunk/include/__std_stream",
|
||||
"//buildtools/third_party/libc++/trunk/include/__string",
|
||||
@@ -378,12 +51,14 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/fuchsia/xlocale.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/ibm/gettod_zos.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/ibm/limits.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/ibm/locale_mgmt_aix.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/ibm/locale_mgmt_zos.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/ibm/nanosleep.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/ibm/support.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/ibm/xlocale.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/musl/xlocale.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/newlib/xlocale.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/nuttx/xlocale.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/openbsd/xlocale.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/solaris/floatingpoint.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/solaris/wchar.h",
|
||||
@@ -393,30 +68,11 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/xlocale/__nop_locale_mgmt.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/xlocale/__posix_l_fallback.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__support/xlocale/__strtonum_fallback.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__thread/poll_with_backoff.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__thread/timed_backoff_policy.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__threading_support",
|
||||
"//buildtools/third_party/libc++/trunk/include/__tree",
|
||||
"//buildtools/third_party/libc++/trunk/include/__tuple",
|
||||
"//buildtools/third_party/libc++/trunk/include/__undef_macros",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/as_const.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/auto_cast.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/cmp.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/declval.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/exchange.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/forward.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/in_place.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/integer_sequence.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/move.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/pair.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/piecewise_construct.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/priority_tag.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/rel_ops.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/swap.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/to_underlying.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/transaction.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__utility/unreachable.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__variant/monostate.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/algorithm",
|
||||
"//buildtools/third_party/libc++/trunk/include/any",
|
||||
"//buildtools/third_party/libc++/trunk/include/array",
|
||||
@@ -443,7 +99,6 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/complex.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/concepts",
|
||||
"//buildtools/third_party/libc++/trunk/include/condition_variable",
|
||||
"//buildtools/third_party/libc++/trunk/include/coroutine",
|
||||
"//buildtools/third_party/libc++/trunk/include/csetjmp",
|
||||
"//buildtools/third_party/libc++/trunk/include/csignal",
|
||||
"//buildtools/third_party/libc++/trunk/include/cstdarg",
|
||||
@@ -456,7 +111,6 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/ctgmath",
|
||||
"//buildtools/third_party/libc++/trunk/include/ctime",
|
||||
"//buildtools/third_party/libc++/trunk/include/ctype.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/cuchar",
|
||||
"//buildtools/third_party/libc++/trunk/include/cwchar",
|
||||
"//buildtools/third_party/libc++/trunk/include/cwctype",
|
||||
"//buildtools/third_party/libc++/trunk/include/deque",
|
||||
@@ -468,6 +122,7 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/experimental/algorithm",
|
||||
"//buildtools/third_party/libc++/trunk/include/experimental/coroutine",
|
||||
"//buildtools/third_party/libc++/trunk/include/experimental/deque",
|
||||
"//buildtools/third_party/libc++/trunk/include/experimental/filesystem",
|
||||
"//buildtools/third_party/libc++/trunk/include/experimental/forward_list",
|
||||
"//buildtools/third_party/libc++/trunk/include/experimental/functional",
|
||||
"//buildtools/third_party/libc++/trunk/include/experimental/iterator",
|
||||
@@ -550,7 +205,6 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/type_traits",
|
||||
"//buildtools/third_party/libc++/trunk/include/typeindex",
|
||||
"//buildtools/third_party/libc++/trunk/include/typeinfo",
|
||||
"//buildtools/third_party/libc++/trunk/include/uchar.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/unordered_map",
|
||||
"//buildtools/third_party/libc++/trunk/include/unordered_set",
|
||||
"//buildtools/third_party/libc++/trunk/include/utility",
|
||||
|
||||
@@ -20,7 +20,7 @@ const spawnUpdate = function (args: string[], detached: boolean, callback: Funct
|
||||
|
||||
try {
|
||||
// Ensure we don't spawn multiple squirrel processes
|
||||
// Process spawned, same args: Attach events to already running process
|
||||
// Process spawned, same args: Attach events to alread running process
|
||||
// Process spawned, different args: Return with error
|
||||
// No process spawned: Spawn new process
|
||||
if (spawnedProcess && !isSameArgs(args)) {
|
||||
|
||||
@@ -142,7 +142,7 @@ Menu.prototype.insert = function (pos, item) {
|
||||
if (item.icon) this.setIcon(pos, item.icon);
|
||||
if (item.role) this.setRole(pos, item.role);
|
||||
|
||||
// Make menu accessible to items.
|
||||
// Make menu accessable to items.
|
||||
item.overrideReadOnlyProperty('menu', this);
|
||||
|
||||
// Remember the items.
|
||||
|
||||
@@ -22,7 +22,6 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'Notification', loader: () => require('./notification') },
|
||||
{ name: 'powerMonitor', loader: () => require('./power-monitor') },
|
||||
{ name: 'powerSaveBlocker', loader: () => require('./power-save-blocker') },
|
||||
{ name: 'pushNotifications', loader: () => require('./push-notifications') },
|
||||
{ name: 'protocol', loader: () => require('./protocol') },
|
||||
{ name: 'safeStorage', loader: () => require('./safe-storage') },
|
||||
{ name: 'screen', loader: () => require('./screen') },
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
const { pushNotifications } = process._linkedBinding('electron_browser_push_notifications');
|
||||
|
||||
export default pushNotifications;
|
||||
@@ -10,7 +10,7 @@ import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-util
|
||||
import { MessagePortMain } from '@electron/internal/browser/message-port-main';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
// session is not used here, the purpose is to make sure session is initialized
|
||||
// session is not used here, the purpose is to make sure session is initalized
|
||||
// before the webContents module.
|
||||
// eslint-disable-next-line
|
||||
session
|
||||
@@ -63,20 +63,6 @@ const PDFPageSizes: Record<string, ElectronInternal.MediaSize> = {
|
||||
}
|
||||
} as const;
|
||||
|
||||
const paperFormats: Record<string, ElectronInternal.PageSize> = {
|
||||
letter: { width: 8.5, height: 11 },
|
||||
legal: { width: 8.5, height: 14 },
|
||||
tabloid: { width: 11, height: 17 },
|
||||
ledger: { width: 17, height: 11 },
|
||||
a0: { width: 33.1, height: 46.8 },
|
||||
a1: { width: 23.4, height: 33.1 },
|
||||
a2: { width: 16.54, height: 23.4 },
|
||||
a3: { width: 11.7, height: 16.54 },
|
||||
a4: { width: 8.27, height: 11.7 },
|
||||
a5: { width: 5.83, height: 8.27 },
|
||||
a6: { width: 4.13, height: 5.83 }
|
||||
} as const;
|
||||
|
||||
// The minimum micron size Chromium accepts is that where:
|
||||
// Per printing/units.h:
|
||||
// * kMicronsPerInch - Length of an inch in 0.001mm unit.
|
||||
@@ -90,6 +76,42 @@ const isValidCustomPageSize = (width: number, height: number) => {
|
||||
return [width, height].every(x => x > 352);
|
||||
};
|
||||
|
||||
// Default printing setting
|
||||
const defaultPrintingSetting = {
|
||||
// Customizable.
|
||||
pageRange: [] as {from: number, to: number}[],
|
||||
mediaSize: {} as ElectronInternal.MediaSize,
|
||||
landscape: false,
|
||||
headerFooterEnabled: false,
|
||||
marginsType: 0,
|
||||
scaleFactor: 100,
|
||||
shouldPrintBackgrounds: false,
|
||||
shouldPrintSelectionOnly: false,
|
||||
// Non-customizable.
|
||||
printWithCloudPrint: false,
|
||||
printWithPrivet: false,
|
||||
printWithExtension: false,
|
||||
pagesPerSheet: 1,
|
||||
isFirstRequest: false,
|
||||
previewUIID: 0,
|
||||
// True, if the document source is modifiable. e.g. HTML and not PDF.
|
||||
previewModifiable: true,
|
||||
printToPDF: true,
|
||||
deviceName: 'Save as PDF',
|
||||
generateDraftData: true,
|
||||
dpiHorizontal: 72,
|
||||
dpiVertical: 72,
|
||||
rasterizePDF: false,
|
||||
duplex: 0,
|
||||
copies: 1,
|
||||
// 2 = color - see ColorModel in //printing/print_job_constants.h
|
||||
color: 2,
|
||||
collate: true,
|
||||
printerType: 2,
|
||||
title: undefined as string | undefined,
|
||||
url: undefined as string | undefined
|
||||
} as const;
|
||||
|
||||
// JavaScript implementations of WebContents.
|
||||
const binding = process._linkedBinding('electron_browser_web_contents');
|
||||
const printing = process._linkedBinding('electron_browser_printing');
|
||||
@@ -124,6 +146,13 @@ WebContents.prototype.sendToFrame = function (frameId, channel, ...args) {
|
||||
return true;
|
||||
};
|
||||
|
||||
WebContents.prototype._sendToFrameInternal = function (frameId, channel, ...args) {
|
||||
const frame = getWebFrame(this, frameId);
|
||||
if (!frame) return false;
|
||||
frame._sendInternal(channel, ...args);
|
||||
return true;
|
||||
};
|
||||
|
||||
// Following methods are mapped to webFrame.
|
||||
const webFrameMethods = [
|
||||
'insertCSS',
|
||||
@@ -164,136 +193,136 @@ WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (worldId
|
||||
let pendingPromise: Promise<any> | undefined;
|
||||
WebContents.prototype.printToPDF = async function (options) {
|
||||
const printSettings: Record<string, any> = {
|
||||
requestID: getNextId(),
|
||||
landscape: false,
|
||||
displayHeaderFooter: false,
|
||||
headerTemplate: '',
|
||||
footerTemplate: '',
|
||||
printBackground: false,
|
||||
scale: 1,
|
||||
paperWidth: 8.5,
|
||||
paperHeight: 11,
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
marginLeft: 0,
|
||||
marginRight: 0,
|
||||
pageRanges: '',
|
||||
preferCSSPageSize: false
|
||||
...defaultPrintingSetting,
|
||||
requestID: getNextId()
|
||||
};
|
||||
|
||||
if (options.landscape !== undefined) {
|
||||
if (typeof options.landscape !== 'boolean') {
|
||||
return Promise.reject(new Error('landscape must be a Boolean'));
|
||||
const error = new Error('landscape must be a Boolean');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
printSettings.landscape = options.landscape;
|
||||
}
|
||||
|
||||
if (options.displayHeaderFooter !== undefined) {
|
||||
if (typeof options.displayHeaderFooter !== 'boolean') {
|
||||
return Promise.reject(new Error('displayHeaderFooter must be a Boolean'));
|
||||
if (options.scaleFactor !== undefined) {
|
||||
if (typeof options.scaleFactor !== 'number') {
|
||||
const error = new Error('scaleFactor must be a Number');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
printSettings.displayHeaderFooter = options.displayHeaderFooter;
|
||||
printSettings.scaleFactor = options.scaleFactor;
|
||||
}
|
||||
|
||||
if (options.marginsType !== undefined) {
|
||||
if (typeof options.marginsType !== 'number') {
|
||||
const error = new Error('marginsType must be a Number');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
printSettings.marginsType = options.marginsType;
|
||||
}
|
||||
|
||||
if (options.printSelectionOnly !== undefined) {
|
||||
if (typeof options.printSelectionOnly !== 'boolean') {
|
||||
const error = new Error('printSelectionOnly must be a Boolean');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
printSettings.shouldPrintSelectionOnly = options.printSelectionOnly;
|
||||
}
|
||||
|
||||
if (options.printBackground !== undefined) {
|
||||
if (typeof options.printBackground !== 'boolean') {
|
||||
return Promise.reject(new Error('printBackground must be a Boolean'));
|
||||
const error = new Error('printBackground must be a Boolean');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
printSettings.shouldPrintBackgrounds = options.printBackground;
|
||||
}
|
||||
|
||||
if (options.scale !== undefined) {
|
||||
if (typeof options.scale !== 'number') {
|
||||
return Promise.reject(new Error('scale must be a Number'));
|
||||
}
|
||||
printSettings.scaleFactor = options.scale;
|
||||
}
|
||||
|
||||
const { pageSize } = options;
|
||||
if (pageSize !== undefined) {
|
||||
if (typeof pageSize === 'string') {
|
||||
const format = paperFormats[pageSize.toLowerCase()];
|
||||
if (!format) {
|
||||
return Promise.reject(new Error(`Invalid pageSize ${pageSize}`));
|
||||
}
|
||||
|
||||
printSettings.paperWidth = format.width;
|
||||
printSettings.paperHeight = format.height;
|
||||
} else if (typeof options.pageSize === 'object') {
|
||||
if (!pageSize.height || !pageSize.width) {
|
||||
return Promise.reject(new Error('height and width properties are required for pageSize'));
|
||||
}
|
||||
|
||||
printSettings.paperWidth = pageSize.width;
|
||||
printSettings.paperHeight = pageSize.height;
|
||||
} else {
|
||||
return Promise.reject(new Error('pageSize must be a String or Object'));
|
||||
}
|
||||
}
|
||||
|
||||
const { margins } = options;
|
||||
if (margins !== undefined) {
|
||||
if (typeof margins !== 'object') {
|
||||
return Promise.reject(new Error('margins must be an Object'));
|
||||
}
|
||||
|
||||
if (margins.top !== undefined) {
|
||||
if (typeof margins.top !== 'number') {
|
||||
return Promise.reject(new Error('margins.top must be a Number'));
|
||||
}
|
||||
printSettings.marginTop = margins.top;
|
||||
}
|
||||
|
||||
if (margins.bottom !== undefined) {
|
||||
if (typeof margins.bottom !== 'number') {
|
||||
return Promise.reject(new Error('margins.bottom must be a Number'));
|
||||
}
|
||||
printSettings.marginBottom = margins.bottom;
|
||||
}
|
||||
|
||||
if (margins.left !== undefined) {
|
||||
if (typeof margins.left !== 'number') {
|
||||
return Promise.reject(new Error('margins.left must be a Number'));
|
||||
}
|
||||
printSettings.marginLeft = margins.left;
|
||||
}
|
||||
|
||||
if (margins.right !== undefined) {
|
||||
if (typeof margins.right !== 'number') {
|
||||
return Promise.reject(new Error('margins.right must be a Number'));
|
||||
}
|
||||
printSettings.marginRight = margins.right;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.pageRanges !== undefined) {
|
||||
if (typeof options.pageRanges !== 'string') {
|
||||
return Promise.reject(new Error('printBackground must be a String'));
|
||||
const pageRanges = options.pageRanges;
|
||||
if (!Object.prototype.hasOwnProperty.call(pageRanges, 'from') || !Object.prototype.hasOwnProperty.call(pageRanges, 'to')) {
|
||||
const error = new Error('pageRanges must be an Object with \'from\' and \'to\' properties');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
printSettings.pageRanges = options.pageRanges;
|
||||
|
||||
if (typeof pageRanges.from !== 'number') {
|
||||
const error = new Error('pageRanges.from must be a Number');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
if (typeof pageRanges.to !== 'number') {
|
||||
const error = new Error('pageRanges.to must be a Number');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
// Chromium uses 1-based page ranges, so increment each by 1.
|
||||
printSettings.pageRange = [{
|
||||
from: pageRanges.from + 1,
|
||||
to: pageRanges.to + 1
|
||||
}];
|
||||
}
|
||||
|
||||
if (options.headerTemplate !== undefined) {
|
||||
if (typeof options.headerTemplate !== 'string') {
|
||||
return Promise.reject(new Error('headerTemplate must be a String'));
|
||||
if (options.headerFooter !== undefined) {
|
||||
const headerFooter = options.headerFooter;
|
||||
printSettings.headerFooterEnabled = true;
|
||||
if (typeof headerFooter === 'object') {
|
||||
if (!headerFooter.url || !headerFooter.title) {
|
||||
const error = new Error('url and title properties are required for headerFooter');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
if (typeof headerFooter.title !== 'string') {
|
||||
const error = new Error('headerFooter.title must be a String');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
printSettings.title = headerFooter.title;
|
||||
|
||||
if (typeof headerFooter.url !== 'string') {
|
||||
const error = new Error('headerFooter.url must be a String');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
printSettings.url = headerFooter.url;
|
||||
} else {
|
||||
const error = new Error('headerFooter must be an Object');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
printSettings.headerTemplate = options.headerTemplate;
|
||||
}
|
||||
|
||||
if (options.footerTemplate !== undefined) {
|
||||
if (typeof options.footerTemplate !== 'string') {
|
||||
return Promise.reject(new Error('footerTemplate must be a String'));
|
||||
// Optionally set size for PDF.
|
||||
if (options.pageSize !== undefined) {
|
||||
const pageSize = options.pageSize;
|
||||
if (typeof pageSize === 'object') {
|
||||
if (!pageSize.height || !pageSize.width) {
|
||||
const error = new Error('height and width properties are required for pageSize');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
// Dimensions in Microns - 1 meter = 10^6 microns
|
||||
const height = Math.ceil(pageSize.height);
|
||||
const width = Math.ceil(pageSize.width);
|
||||
if (!isValidCustomPageSize(width, height)) {
|
||||
const error = new Error('height and width properties must be minimum 352 microns.');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
printSettings.mediaSize = {
|
||||
name: 'CUSTOM',
|
||||
custom_display_name: 'Custom',
|
||||
height_microns: height,
|
||||
width_microns: width
|
||||
};
|
||||
} else if (Object.prototype.hasOwnProperty.call(PDFPageSizes, pageSize)) {
|
||||
printSettings.mediaSize = PDFPageSizes[pageSize];
|
||||
} else {
|
||||
const error = new Error(`Unsupported pageSize: ${pageSize}`);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
printSettings.footerTemplate = options.footerTemplate;
|
||||
}
|
||||
|
||||
if (options.preferCSSPageSize !== undefined) {
|
||||
if (typeof options.preferCSSPageSize !== 'boolean') {
|
||||
return Promise.reject(new Error('footerTemplate must be a String'));
|
||||
}
|
||||
printSettings.preferCSSPageSize = options.preferCSSPageSize;
|
||||
} else {
|
||||
printSettings.mediaSize = PDFPageSizes.A4;
|
||||
}
|
||||
|
||||
// Chromium expects this in a 0-100 range number, not as float
|
||||
printSettings.scaleFactor = Math.ceil(printSettings.scaleFactor) % 100;
|
||||
// PrinterType enum from //printing/print_job_constants.h
|
||||
printSettings.printerType = 2;
|
||||
if (this._printToPDF) {
|
||||
if (pendingPromise) {
|
||||
pendingPromise = pendingPromise.then(() => this._printToPDF(printSettings));
|
||||
|
||||
@@ -31,7 +31,7 @@ export const setDefaultApplicationMenu = () => {
|
||||
{
|
||||
label: 'Community Discussions',
|
||||
click: async () => {
|
||||
await shell.openExternal('https://discord.gg/electronjs');
|
||||
await shell.openExternal('https://discord.com/invite/APGC3k5yaH');
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ import { webViewEvents } from '@electron/internal/browser/web-view-events';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
interface GuestInstance {
|
||||
elementInstanceId: number;
|
||||
elementInstanceId?: number;
|
||||
visibilityState?: VisibilityState;
|
||||
embedder: Electron.WebContents;
|
||||
guest: Electron.WebContents;
|
||||
@@ -46,7 +46,6 @@ function makeWebPreferences (embedder: Electron.WebContents, params: Record<stri
|
||||
webSecurity: !params.disablewebsecurity,
|
||||
enableBlinkFeatures: params.blinkfeatures,
|
||||
disableBlinkFeatures: params.disableblinkfeatures,
|
||||
partition: params.partition,
|
||||
...parsedWebPreferences
|
||||
};
|
||||
|
||||
@@ -88,26 +87,14 @@ function makeLoadURLOptions (params: Record<string, any>) {
|
||||
|
||||
// Create a new guest instance.
|
||||
const createGuest = function (embedder: Electron.WebContents, embedderFrameId: number, elementInstanceId: number, params: Record<string, any>) {
|
||||
const webPreferences = makeWebPreferences(embedder, params);
|
||||
const event = eventBinding.createWithSender(embedder);
|
||||
|
||||
const { instanceId } = params;
|
||||
|
||||
embedder.emit('will-attach-webview', event, webPreferences, params);
|
||||
if (event.defaultPrevented) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const guest = (webContents as typeof ElectronInternal.WebContents).create({
|
||||
...webPreferences,
|
||||
type: 'webview',
|
||||
partition: params.partition,
|
||||
embedder
|
||||
});
|
||||
|
||||
const guestInstanceId = guest.id;
|
||||
guestInstances.set(guestInstanceId, {
|
||||
elementInstanceId,
|
||||
guest,
|
||||
embedder
|
||||
});
|
||||
@@ -121,8 +108,11 @@ const createGuest = function (embedder: Electron.WebContents, embedderFrameId: n
|
||||
|
||||
// Init guest web view after attached.
|
||||
guest.once('did-attach' as any, function (this: Electron.WebContents, event: Electron.Event) {
|
||||
const params = this.attachParams!;
|
||||
delete this.attachParams;
|
||||
|
||||
const previouslyAttached = this.viewInstanceId != null;
|
||||
this.viewInstanceId = instanceId;
|
||||
this.viewInstanceId = params.instanceId;
|
||||
|
||||
// Only load URL and set size on first attach
|
||||
if (previouslyAttached) {
|
||||
@@ -130,7 +120,7 @@ const createGuest = function (embedder: Electron.WebContents, embedderFrameId: n
|
||||
}
|
||||
|
||||
if (params.src) {
|
||||
this.loadURL(params.src, makeLoadURLOptions(params));
|
||||
this.loadURL(params.src, params.opts);
|
||||
}
|
||||
embedder.emit('did-attach-webview', event, guest);
|
||||
});
|
||||
@@ -183,25 +173,78 @@ const createGuest = function (embedder: Electron.WebContents, embedderFrameId: n
|
||||
}
|
||||
});
|
||||
|
||||
if (attachGuest(embedder, embedderFrameId, elementInstanceId, guestInstanceId, params)) {
|
||||
return guestInstanceId;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Attach the guest to an element of embedder.
|
||||
const attachGuest = function (embedder: Electron.WebContents, embedderFrameId: number, elementInstanceId: number, guestInstanceId: number, params: Record<string, any>) {
|
||||
// Destroy the old guest when attaching.
|
||||
const key = `${embedder.id}-${elementInstanceId}`;
|
||||
const oldGuestInstanceId = embedderElementsMap.get(key);
|
||||
if (oldGuestInstanceId != null) {
|
||||
// Reattachment to the same guest is just a no-op.
|
||||
if (oldGuestInstanceId === guestInstanceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const oldGuestInstance = guestInstances.get(oldGuestInstanceId);
|
||||
if (oldGuestInstance) {
|
||||
oldGuestInstance.guest.detachFromOuterFrame();
|
||||
}
|
||||
}
|
||||
|
||||
const guestInstance = guestInstances.get(guestInstanceId);
|
||||
// If this isn't a valid guest instance then do nothing.
|
||||
if (!guestInstance) {
|
||||
console.error(new Error(`Guest attach failed: Invalid guestInstanceId ${guestInstanceId}`));
|
||||
return false;
|
||||
}
|
||||
const { guest } = guestInstance;
|
||||
if (guest.hostWebContents !== embedder) {
|
||||
console.error(new Error(`Guest attach failed: Access denied to guestInstanceId ${guestInstanceId}`));
|
||||
return false;
|
||||
}
|
||||
|
||||
const { instanceId } = params;
|
||||
|
||||
// If this guest is already attached to an element then remove it
|
||||
if (guestInstance.elementInstanceId) {
|
||||
const oldKey = `${guestInstance.embedder.id}-${guestInstance.elementInstanceId}`;
|
||||
embedderElementsMap.delete(oldKey);
|
||||
|
||||
// Remove guest from embedder if moving across web views
|
||||
if (guest.viewInstanceId !== instanceId) {
|
||||
webViewManager.removeGuest(guestInstance.embedder, guestInstanceId);
|
||||
guestInstance.embedder._sendInternal(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DESTROY_GUEST}-${guest.viewInstanceId}`);
|
||||
}
|
||||
}
|
||||
|
||||
const webPreferences = makeWebPreferences(embedder, params);
|
||||
|
||||
const event = eventBinding.createWithSender(embedder);
|
||||
embedder.emit('will-attach-webview', event, webPreferences, params);
|
||||
if (event.defaultPrevented) {
|
||||
if (guest.viewInstanceId == null) guest.viewInstanceId = instanceId;
|
||||
guest.destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
guest.attachParams = { instanceId, src: params.src, opts: makeLoadURLOptions(params) };
|
||||
embedderElementsMap.set(key, guestInstanceId);
|
||||
|
||||
guest.setEmbedder(embedder);
|
||||
guestInstance.embedder = embedder;
|
||||
guestInstance.elementInstanceId = elementInstanceId;
|
||||
|
||||
watchEmbedder(embedder);
|
||||
|
||||
webViewManager.addGuest(guestInstanceId, embedder, guest, webPreferences);
|
||||
guest.attachToIframe(embedder, embedderFrameId);
|
||||
|
||||
return guestInstanceId;
|
||||
return true;
|
||||
};
|
||||
|
||||
// Remove an guest-embedder relationship.
|
||||
|
||||
@@ -9,6 +9,7 @@ export const enum IPC_MESSAGES {
|
||||
|
||||
GUEST_INSTANCE_VISIBILITY_CHANGE = 'GUEST_INSTANCE_VISIBILITY_CHANGE',
|
||||
|
||||
GUEST_VIEW_INTERNAL_DESTROY_GUEST = 'GUEST_VIEW_INTERNAL_DESTROY_GUEST',
|
||||
GUEST_VIEW_INTERNAL_DISPATCH_EVENT = 'GUEST_VIEW_INTERNAL_DISPATCH_EVENT',
|
||||
|
||||
GUEST_VIEW_MANAGER_CREATE_AND_ATTACH_GUEST = 'GUEST_VIEW_MANAGER_CREATE_AND_ATTACH_GUEST',
|
||||
|
||||
@@ -6,15 +6,30 @@ const { mainFrame: webFrame } = process._linkedBinding('electron_renderer_web_fr
|
||||
|
||||
export interface GuestViewDelegate {
|
||||
dispatchEvent (eventName: string, props: Record<string, any>): void;
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
const DEPRECATED_EVENTS: Record<string, string> = {
|
||||
'page-title-updated': 'page-title-set'
|
||||
} as const;
|
||||
|
||||
export function registerEvents (viewInstanceId: number, delegate: GuestViewDelegate) {
|
||||
ipcRendererInternal.on(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DESTROY_GUEST}-${viewInstanceId}`, function () {
|
||||
delegate.reset();
|
||||
delegate.dispatchEvent('destroyed', {});
|
||||
});
|
||||
|
||||
ipcRendererInternal.on(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DISPATCH_EVENT}-${viewInstanceId}`, function (event, eventName, props) {
|
||||
if (DEPRECATED_EVENTS[eventName] != null) {
|
||||
delegate.dispatchEvent(DEPRECATED_EVENTS[eventName], props);
|
||||
}
|
||||
|
||||
delegate.dispatchEvent(eventName, props);
|
||||
});
|
||||
}
|
||||
|
||||
export function deregisterEvents (viewInstanceId: number) {
|
||||
ipcRendererInternal.removeAllListeners(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DESTROY_GUEST}-${viewInstanceId}`);
|
||||
ipcRendererInternal.removeAllListeners(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DISPATCH_EVENT}-${viewInstanceId}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ const defineWebViewElement = (hooks: WebViewImplHooks) => {
|
||||
}
|
||||
if (!internal.elementAttached) {
|
||||
hooks.guestViewInternal.registerEvents(internal.viewInstanceId, {
|
||||
dispatchEvent: internal.dispatchEvent.bind(internal)
|
||||
dispatchEvent: internal.dispatchEvent.bind(internal),
|
||||
reset: internal.reset.bind(internal)
|
||||
});
|
||||
internal.elementAttached = true;
|
||||
(internal.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC) as SrcAttribute).parse();
|
||||
|
||||
@@ -191,7 +191,7 @@ export class WebViewImpl {
|
||||
|
||||
attachGuestInstance (guestInstanceId: number) {
|
||||
if (guestInstanceId === -1) {
|
||||
this.dispatchEvent('destroyed');
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "21.0.0-alpha.3",
|
||||
"version": "20.0.0-beta.4",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
@@ -47,8 +47,8 @@
|
||||
"express": "^4.16.4",
|
||||
"folder-hash": "^2.1.1",
|
||||
"fs-extra": "^9.0.1",
|
||||
"got": "^11.8.5",
|
||||
"husky": "^8.0.1",
|
||||
"got": "^6.3.0",
|
||||
"husky": "^6.0.0",
|
||||
"klaw": "^3.0.0",
|
||||
"lint": "^1.1.2",
|
||||
"lint-staged": "^10.2.11",
|
||||
|
||||
@@ -58,10 +58,10 @@ index 852b76bea69988e0b3ac76a17b603128f239dde0..d443f4dc2daea0b7aa86ae75d31d995f
|
||||
callback(EVP_aes_192_ctr(), "aes-192-ctr", NULL, arg);
|
||||
callback(EVP_aes_256_ctr(), "aes-256-ctr", NULL, arg);
|
||||
diff --git a/include/openssl/cipher.h b/include/openssl/cipher.h
|
||||
index 380d25d9c2a8efb0636db5749a8e3b1ba6908ad5..7a5aa1c142e15cf06e63882e83d82a93c0d38785 100644
|
||||
index 2458847e5640fe955a9971aa77c27251e5091db5..a0b3ac5f6b55921a542f27108beca93d6372c6fc 100644
|
||||
--- a/include/openssl/cipher.h
|
||||
+++ b/include/openssl/cipher.h
|
||||
@@ -460,6 +460,7 @@ OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_ecb(void);
|
||||
@@ -448,6 +448,7 @@ OPENSSL_EXPORT const EVP_CIPHER *EVP_des_ede3_ecb(void);
|
||||
|
||||
// EVP_aes_128_cfb128 is only available in decrepit.
|
||||
OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_cfb128(void);
|
||||
|
||||
@@ -12,6 +12,7 @@ webview_cross_drag.patch
|
||||
gin_enable_disable_v8_platform.patch
|
||||
disable-redraw-lock.patch
|
||||
enable_reset_aspect_ratio.patch
|
||||
v8_context_snapshot_generator.patch
|
||||
boringssl_build_gn.patch
|
||||
pepper_plugin_support.patch
|
||||
gtk_visibility.patch
|
||||
@@ -74,6 +75,7 @@ skip_atk_toolchain_check.patch
|
||||
worker_feat_add_hook_to_notify_script_ready.patch
|
||||
chore_provide_iswebcontentscreationoverridden_with_full_params.patch
|
||||
fix_properly_honor_printing_page_ranges.patch
|
||||
chore_expose_v8_initialization_isolate_callbacks.patch
|
||||
export_gin_v8platform_pageallocator_for_usage_outside_of_the_gin.patch
|
||||
fix_export_zlib_symbols.patch
|
||||
don_t_use_potentially_null_getwebframe_-_view_when_get_blink.patch
|
||||
@@ -109,10 +111,4 @@ make_gtk_getlibgtk_public.patch
|
||||
build_disable_print_content_analysis.patch
|
||||
custom_protocols_plzserviceworker.patch
|
||||
feat_filter_out_non-shareable_windows_in_the_current_application_in.patch
|
||||
fix_allow_guest_webcontents_to_enter_fullscreen.patch
|
||||
disable_freezing_flags_after_init_in_node.patch
|
||||
short-circuit_permissions_checks_in_mediastreamdevicescontroller.patch
|
||||
chore_add_electron_deps_to_gitignores.patch
|
||||
chore_allow_chromium_to_handle_synthetic_mouse_events_for_touch.patch
|
||||
add_maximized_parameter_to_linuxui_getwindowframeprovider.patch
|
||||
add_electron_deps_to_license_credits_file.patch
|
||||
posix_replace_doubleforkandexec_with_forkandspawn.patch
|
||||
|
||||
@@ -10,10 +10,10 @@ Allows Electron to restore WER when ELECTRON_DEFAULT_ERROR_MODE is set.
|
||||
This should be upstreamed.
|
||||
|
||||
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
|
||||
index b692a49b71661b8394c1126250fb150653aece97..c087c0f99a15edd3a9c776a68c76b2cf46257123 100644
|
||||
index e0ff6fae1e96699e7cb54c9e82a3c68a8e95602b..2179a906bb6c93fbfaa8e7b7e64fddfaab034e94 100644
|
||||
--- a/content/gpu/gpu_main.cc
|
||||
+++ b/content/gpu/gpu_main.cc
|
||||
@@ -239,6 +239,10 @@ int GpuMain(MainFunctionParams parameters) {
|
||||
@@ -241,6 +241,10 @@ int GpuMain(MainFunctionParams parameters) {
|
||||
// to the GpuProcessHost once the GpuServiceImpl has started.
|
||||
viz::GpuServiceImpl::InstallPreInitializeLogHandler();
|
||||
|
||||
@@ -24,9 +24,9 @@ index b692a49b71661b8394c1126250fb150653aece97..c087c0f99a15edd3a9c776a68c76b2cf
|
||||
// We are experiencing what appear to be memory-stomp issues in the GPU
|
||||
// process. These issues seem to be impacting the task executor and listeners
|
||||
// registered to it. Create the task executor on the heap to guard against
|
||||
@@ -337,7 +341,6 @@ int GpuMain(MainFunctionParams parameters) {
|
||||
ChildProcess gpu_process(io_thread_type);
|
||||
DCHECK(base::ThreadPoolInstance::Get()->WasStarted());
|
||||
@@ -347,7 +351,6 @@ int GpuMain(MainFunctionParams parameters) {
|
||||
GpuProcess gpu_process(io_thread_priority);
|
||||
#endif
|
||||
|
||||
- auto* client = GetContentClient()->gpu();
|
||||
if (client)
|
||||
|
||||
@@ -10,7 +10,7 @@ DidCreateScriptContext is called, not all JS APIs are available in the
|
||||
context, which can cause some preload scripts to trip.
|
||||
|
||||
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h
|
||||
index 5a7d3da58451f491ed6dfabd3bc31a645843bb60..36cbf8c5c01330acc8b3a708bd6481ede21d73be 100644
|
||||
index d921125d153742dd09e34418c19195a3d61bef1f..5348c3289a94c86bbbc9bb07be26cc56b4986788 100644
|
||||
--- a/content/public/renderer/render_frame_observer.h
|
||||
+++ b/content/public/renderer/render_frame_observer.h
|
||||
@@ -136,6 +136,8 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
|
||||
@@ -23,10 +23,10 @@ index 5a7d3da58451f491ed6dfabd3bc31a645843bb60..36cbf8c5c01330acc8b3a708bd6481ed
|
||||
int32_t world_id) {}
|
||||
virtual void DidClearWindowObject() {}
|
||||
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
|
||||
index 4a69ce45890fd9ab730eef460396ab495b7a332a..3e186230715aaf840959a93038167749e3735a08 100644
|
||||
index 831db39365764d4001b8d602b225f157d3562ca8..4aabe0781d9e4150dddce76a50b993d0b8da8068 100644
|
||||
--- a/content/renderer/render_frame_impl.cc
|
||||
+++ b/content/renderer/render_frame_impl.cc
|
||||
@@ -4435,6 +4435,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
@@ -4502,6 +4502,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
observer.DidCreateScriptContext(context, world_id);
|
||||
}
|
||||
|
||||
@@ -40,10 +40,10 @@ index 4a69ce45890fd9ab730eef460396ab495b7a332a..3e186230715aaf840959a93038167749
|
||||
int world_id) {
|
||||
for (auto& observer : observers_)
|
||||
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
|
||||
index 351a3a257a3eca98c4a2caf724714cbc788b5d72..73dbb5a289411ea32f06cb1ea50ef98153923101 100644
|
||||
index e903ba9ec4f8d32c5d3a6795f0a20f2addf95743..bb9755b981cf96e131e6545f778f73607fabdd02 100644
|
||||
--- a/content/renderer/render_frame_impl.h
|
||||
+++ b/content/renderer/render_frame_impl.h
|
||||
@@ -606,6 +606,8 @@ class CONTENT_EXPORT RenderFrameImpl
|
||||
@@ -604,6 +604,8 @@ class CONTENT_EXPORT RenderFrameImpl
|
||||
uint32_t ng_call_count) override;
|
||||
void DidCreateScriptContext(v8::Local<v8::Context> context,
|
||||
int world_id) override;
|
||||
@@ -53,10 +53,10 @@ index 351a3a257a3eca98c4a2caf724714cbc788b5d72..73dbb5a289411ea32f06cb1ea50ef981
|
||||
int world_id) override;
|
||||
void DidChangeScrollOffset() override;
|
||||
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
|
||||
index acb427e4a6688f14f4a6ceaec8bf3988525c5e08..35623174f16399d5fff637a07554e43c55f902d1 100644
|
||||
index 595441198b5253e5f36f97303e952e642998be39..1b17db7b9285cb874e74abdd896888c12b288565 100644
|
||||
--- a/third_party/blink/public/web/web_local_frame_client.h
|
||||
+++ b/third_party/blink/public/web/web_local_frame_client.h
|
||||
@@ -606,6 +606,9 @@ class BLINK_EXPORT WebLocalFrameClient {
|
||||
@@ -598,6 +598,9 @@ class BLINK_EXPORT WebLocalFrameClient {
|
||||
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) {}
|
||||
|
||||
@@ -67,10 +67,10 @@ index acb427e4a6688f14f4a6ceaec8bf3988525c5e08..35623174f16399d5fff637a07554e43c
|
||||
virtual void WillReleaseScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) {}
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
|
||||
index c8af53d40eaa1dd3a0067948a8cda80d1599cee3..4de918ee52efa7ec27a21aa2f57616d31dfd07d1 100644
|
||||
index a6ba8411384855c82712960375bc949c5c2bd522..fc86ca807c9c1bda9236160580b094153778e18b 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
|
||||
@@ -209,6 +209,7 @@ void LocalWindowProxy::Initialize() {
|
||||
@@ -207,6 +207,7 @@ void LocalWindowProxy::Initialize() {
|
||||
}
|
||||
|
||||
InstallConditionalFeatures();
|
||||
@@ -79,10 +79,10 @@ index c8af53d40eaa1dd3a0067948a8cda80d1599cee3..4de918ee52efa7ec27a21aa2f57616d3
|
||||
if (World().IsMainWorld()) {
|
||||
GetFrame()->Loader().DispatchDidClearWindowObjectInMainWorld();
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
index 27b366933ce11a029920b9f85060f8cce8deaacd..110996a9d55c1ba779e8aff598e9847dd6a38d86 100644
|
||||
index 6fb24096d3a5415f59cba2a8a5a6f36fe838dcc1..a4089fb3989ecd37d5b01baeb03c2ac1f4f05b53 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
|
||||
@@ -301,6 +301,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
|
||||
@@ -298,6 +298,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
|
||||
|
||||
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) = 0;
|
||||
@@ -92,7 +92,7 @@ index 27b366933ce11a029920b9f85060f8cce8deaacd..110996a9d55c1ba779e8aff598e9847d
|
||||
int32_t world_id) = 0;
|
||||
virtual bool AllowScriptExtensions() = 0;
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
|
||||
index 7cbb31ddff83ea89ae879dfe190b62a8cdbeb7cf..ebc2f572b3340b7ca8719073afda8d266b18cbe5 100644
|
||||
index 40042e1fa2622a871d0ed512f1f6fda1cdda56a6..a377548b36712bd4971bae6b4c0afdc5c8fdbdfc 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
|
||||
@@ -273,6 +273,13 @@ void LocalFrameClientImpl::DidCreateScriptContext(
|
||||
@@ -110,7 +110,7 @@ index 7cbb31ddff83ea89ae879dfe190b62a8cdbeb7cf..ebc2f572b3340b7ca8719073afda8d26
|
||||
v8::Local<v8::Context> context,
|
||||
int32_t world_id) {
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
|
||||
index c95ef4a4a3f9d40e0e4bedf6fc42225190626c42..36cc932782437b9f5d301416f5a4e8f48c3c837a 100644
|
||||
index 1f929d9535ca19a2c443e13f2bafce179f5870df..fe7605585501fcc1fd515f1d94fda7e27d5ba632 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
|
||||
@@ -80,6 +80,8 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
|
||||
@@ -123,10 +123,10 @@ index c95ef4a4a3f9d40e0e4bedf6fc42225190626c42..36cc932782437b9f5d301416f5a4e8f4
|
||||
int32_t world_id) override;
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
index d44adfd65bd9a71996cdd323a5220d2dcaa09de2..1011a318a7d79186abe556d03f78badc725c802a 100644
|
||||
index a9bd5283d3c65728dd3293abe88ffd02d3eee4fc..f5e4a927f2f5114e62d76fec86d6a5d2d2321166 100644
|
||||
--- a/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
|
||||
@@ -366,6 +366,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
|
||||
@@ -352,6 +352,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
|
||||
|
||||
void DidCreateScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) override {}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Charles Kerr <charles@charleskerr.com>
|
||||
Date: Tue, 9 Aug 2022 12:35:36 -0500
|
||||
Subject: add electron deps to license credits file
|
||||
|
||||
Ensure that licenses for the dependencies introduced by Electron
|
||||
are included in `LICENSES.chromium.html`
|
||||
|
||||
diff --git a/tools/licenses.py b/tools/licenses.py
|
||||
index a58dbf44370baabbfa2986c734c96a210cc16f1d..1d6934460f788ab76275710e727fb062f5c92b5b 100755
|
||||
--- a/tools/licenses.py
|
||||
+++ b/tools/licenses.py
|
||||
@@ -347,6 +347,32 @@ SPECIAL_CASES = {
|
||||
"License File":
|
||||
"/third_party/swiftshader/third_party/SPIRV-Headers/LICENSE",
|
||||
},
|
||||
+
|
||||
+ os.path.join('third_party', 'electron_node'): {
|
||||
+ "Name": "Node.js",
|
||||
+ "URL": "https://github.com/nodejs/node",
|
||||
+ "License": "MIT",
|
||||
+ "License File": "/third_party/electron_node/LICENSE",
|
||||
+ },
|
||||
+ os.path.join('third_party', 'squirrel.mac'): {
|
||||
+ "Name": "Squirrel",
|
||||
+ "URL": "https://github.com/Squirrel/Squirrel.Mac",
|
||||
+ "License": "MIT",
|
||||
+ "License File": "/third_party/squirrel.mac/LICENSE",
|
||||
+ },
|
||||
+ os.path.join('third_party', 'squirrel.mac', 'vendor', 'mantle'): {
|
||||
+ "Name": "Mantle",
|
||||
+ "URL": "https://github.com/Mantle/Mantle",
|
||||
+ "License": "MIT",
|
||||
+ "License File": "/third_party/squirrel.mac/vendor/mantle/LICENSE.md",
|
||||
+ },
|
||||
+ os.path.join('third_party', 'squirrel.mac', 'vendor', 'ReactiveObjC'): {
|
||||
+ "Name": "ReactiveObjC",
|
||||
+ "URL": "https://github.com/ReactiveCocoa/ReactiveObjC",
|
||||
+ "License": "MIT",
|
||||
+ "License File":
|
||||
+ "/third_party/squirrel.mac/vendor/ReactiveObjC/LICENSE.md",
|
||||
+ },
|
||||
}
|
||||
|
||||
# Special value for 'License File' field used to indicate that the license file
|
||||
@@ -1,176 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: msizanoen1 <msizanoen@qtmlabs.xyz>
|
||||
Date: Tue, 19 Jul 2022 05:11:06 +0200
|
||||
Subject: Add maximized parameter to LinuxUI::GetWindowFrameProvider
|
||||
|
||||
This allows ClientFrameViewLinux to instruct the toolkit to draw the window
|
||||
decorations in maximized mode where needed, preventing empty space caused
|
||||
by decoration shadows and rounded titlebars around the window while maximized.
|
||||
|
||||
diff --git a/ui/gtk/gtk_ui.cc b/ui/gtk/gtk_ui.cc
|
||||
index 50c01fb42bc1a7350fae4773f1b549355c6cdc25..ab49a67e3b20cd240f532cfbf868533bb1f293d8 100644
|
||||
--- a/ui/gtk/gtk_ui.cc
|
||||
+++ b/ui/gtk/gtk_ui.cc
|
||||
@@ -511,13 +511,15 @@ std::unique_ptr<ui::NavButtonProvider> GtkUi::CreateNavButtonProvider() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
-ui::WindowFrameProvider* GtkUi::GetWindowFrameProvider(bool solid_frame) {
|
||||
+ui::WindowFrameProvider* GtkUi::GetWindowFrameProvider(bool solid_frame, bool maximized) {
|
||||
if (!GtkCheckVersion(3, 14))
|
||||
return nullptr;
|
||||
auto& provider =
|
||||
- solid_frame ? solid_frame_provider_ : transparent_frame_provider_;
|
||||
+ maximized
|
||||
+ ? (solid_frame ? solid_maximized_frame_provider_ : transparent_maximized_frame_provider_)
|
||||
+ : (solid_frame ? solid_frame_provider_ : transparent_frame_provider_);
|
||||
if (!provider)
|
||||
- provider = std::make_unique<gtk::WindowFrameProviderGtk>(solid_frame);
|
||||
+ provider = std::make_unique<gtk::WindowFrameProviderGtk>(solid_frame, maximized);
|
||||
return provider.get();
|
||||
}
|
||||
|
||||
diff --git a/ui/gtk/gtk_ui.h b/ui/gtk/gtk_ui.h
|
||||
index 5206acf475346f50e0f31b7432d9b93afc3a8ad0..9f2b3cca2337b4528f9451c2fdec7c67021c949f 100644
|
||||
--- a/ui/gtk/gtk_ui.h
|
||||
+++ b/ui/gtk/gtk_ui.h
|
||||
@@ -93,7 +93,7 @@ class GtkUi : public ui::LinuxUi {
|
||||
bool PreferDarkTheme() const override;
|
||||
bool AnimationsEnabled() const override;
|
||||
std::unique_ptr<ui::NavButtonProvider> CreateNavButtonProvider() override;
|
||||
- ui::WindowFrameProvider* GetWindowFrameProvider(bool solid_frame) override;
|
||||
+ ui::WindowFrameProvider* GetWindowFrameProvider(bool solid_frame, bool maximized) override;
|
||||
base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
|
||||
std::string GetCursorThemeName() override;
|
||||
int GetCursorThemeSize() override;
|
||||
@@ -197,6 +197,8 @@ class GtkUi : public ui::LinuxUi {
|
||||
// while Chrome is running.
|
||||
std::unique_ptr<ui::WindowFrameProvider> solid_frame_provider_;
|
||||
std::unique_ptr<ui::WindowFrameProvider> transparent_frame_provider_;
|
||||
+ std::unique_ptr<ui::WindowFrameProvider> solid_maximized_frame_provider_;
|
||||
+ std::unique_ptr<ui::WindowFrameProvider> transparent_maximized_frame_provider_;
|
||||
};
|
||||
|
||||
} // namespace gtk
|
||||
diff --git a/ui/gtk/window_frame_provider_gtk.cc b/ui/gtk/window_frame_provider_gtk.cc
|
||||
index e4dbdad327eb77994ffd7f068c67336a19897915..d3ae0636455489a7c7443df85cb769952c98aca2 100644
|
||||
--- a/ui/gtk/window_frame_provider_gtk.cc
|
||||
+++ b/ui/gtk/window_frame_provider_gtk.cc
|
||||
@@ -38,16 +38,18 @@ std::string GetThemeName() {
|
||||
return theme_string;
|
||||
}
|
||||
|
||||
-GtkCssContext WindowContext(bool solid_frame, bool focused) {
|
||||
+GtkCssContext WindowContext(bool solid_frame, bool maximized, bool focused) {
|
||||
std::string selector = "#window.background.";
|
||||
selector += solid_frame ? "solid-csd" : "csd";
|
||||
+ if (maximized)
|
||||
+ selector += ".maximized";
|
||||
if (!focused)
|
||||
selector += ":inactive";
|
||||
return AppendCssNodeToStyleContext({}, selector);
|
||||
}
|
||||
|
||||
-GtkCssContext DecorationContext(bool solid_frame, bool focused) {
|
||||
- auto context = WindowContext(solid_frame, focused);
|
||||
+GtkCssContext DecorationContext(bool solid_frame, bool maximized, bool focused) {
|
||||
+ auto context = WindowContext(solid_frame, maximized, focused);
|
||||
// GTK4 renders the decoration directly on the window.
|
||||
if (!GtkCheckVersion(4))
|
||||
context = AppendCssNodeToStyleContext(context, "#decoration");
|
||||
@@ -64,8 +66,8 @@ GtkCssContext DecorationContext(bool solid_frame, bool focused) {
|
||||
return context;
|
||||
}
|
||||
|
||||
-GtkCssContext HeaderContext(bool solid_frame, bool focused) {
|
||||
- auto context = WindowContext(solid_frame, focused);
|
||||
+GtkCssContext HeaderContext(bool solid_frame, bool maximized, bool focused) {
|
||||
+ auto context = WindowContext(solid_frame, maximized, focused);
|
||||
context =
|
||||
AppendCssNodeToStyleContext(context, "#headerbar.header-bar.titlebar");
|
||||
if (!focused)
|
||||
@@ -110,8 +112,8 @@ int ComputeTopCornerRadius() {
|
||||
// need to experimentally determine the corner radius by rendering a sample.
|
||||
// Additionally, in GTK4, the headerbar corners get clipped by the window
|
||||
// rather than the headerbar having its own rounded corners.
|
||||
- auto context = GtkCheckVersion(4) ? DecorationContext(false, false)
|
||||
- : HeaderContext(false, false);
|
||||
+ auto context = GtkCheckVersion(4) ? DecorationContext(false, false, false)
|
||||
+ : HeaderContext(false, false, false);
|
||||
ApplyCssToContext(context, R"(window, headerbar {
|
||||
background-image: none;
|
||||
background-color: black;
|
||||
@@ -169,8 +171,8 @@ void WindowFrameProviderGtk::Asset::CloneFrom(
|
||||
unfocused_bitmap = src.unfocused_bitmap;
|
||||
}
|
||||
|
||||
-WindowFrameProviderGtk::WindowFrameProviderGtk(bool solid_frame)
|
||||
- : solid_frame_(solid_frame) {}
|
||||
+WindowFrameProviderGtk::WindowFrameProviderGtk(bool solid_frame, bool maximized)
|
||||
+ : solid_frame_(solid_frame), maximized_(maximized) {}
|
||||
|
||||
WindowFrameProviderGtk::~WindowFrameProviderGtk() = default;
|
||||
|
||||
@@ -264,7 +266,7 @@ void WindowFrameProviderGtk::PaintWindowFrame(gfx::Canvas* canvas,
|
||||
top_area_height_dip * scale - asset.frame_thickness_px.top();
|
||||
|
||||
auto header = PaintHeaderbar({client_bounds_px.width(), top_area_height_px},
|
||||
- HeaderContext(solid_frame_, focused), scale);
|
||||
+ HeaderContext(solid_frame_, maximized_, focused), scale);
|
||||
image = gfx::ImageSkia::CreateFrom1xBitmap(header);
|
||||
// In GTK4, the headerbar gets clipped by the window.
|
||||
if (GtkCheckVersion(4)) {
|
||||
@@ -296,7 +298,7 @@ void WindowFrameProviderGtk::MaybeUpdateBitmaps(float scale) {
|
||||
|
||||
gfx::Rect frame_bounds_dip(kMaxFrameSizeDip, kMaxFrameSizeDip,
|
||||
2 * kMaxFrameSizeDip, 2 * kMaxFrameSizeDip);
|
||||
- auto focused_context = DecorationContext(solid_frame_, true);
|
||||
+ auto focused_context = DecorationContext(solid_frame_, maximized_, true);
|
||||
frame_bounds_dip.Inset(-GtkStyleContextGetPadding(focused_context));
|
||||
frame_bounds_dip.Inset(-GtkStyleContextGetBorder(focused_context));
|
||||
gfx::Size bitmap_size(BitmapSizePx(asset), BitmapSizePx(asset));
|
||||
@@ -304,7 +306,7 @@ void WindowFrameProviderGtk::MaybeUpdateBitmaps(float scale) {
|
||||
PaintBitmap(bitmap_size, frame_bounds_dip, focused_context, scale);
|
||||
asset.unfocused_bitmap =
|
||||
PaintBitmap(bitmap_size, frame_bounds_dip,
|
||||
- DecorationContext(solid_frame_, false), scale);
|
||||
+ DecorationContext(solid_frame_, maximized_, false), scale);
|
||||
|
||||
// In GTK4, there's no way to obtain the frame thickness from CSS values
|
||||
// directly, so we must determine it experimentally based on the drawn
|
||||
diff --git a/ui/gtk/window_frame_provider_gtk.h b/ui/gtk/window_frame_provider_gtk.h
|
||||
index da0f7c33a260f8d98a73c126def30944589001df..a2999a6dcea30a9e468f974301b3a4f03dcb8aeb 100644
|
||||
--- a/ui/gtk/window_frame_provider_gtk.h
|
||||
+++ b/ui/gtk/window_frame_provider_gtk.h
|
||||
@@ -14,7 +14,7 @@ namespace gtk {
|
||||
|
||||
class WindowFrameProviderGtk : public ui::WindowFrameProvider {
|
||||
public:
|
||||
- explicit WindowFrameProviderGtk(bool solid_frame);
|
||||
+ explicit WindowFrameProviderGtk(bool solid_frame, bool maximized);
|
||||
|
||||
WindowFrameProviderGtk(const WindowFrameProviderGtk&) = delete;
|
||||
WindowFrameProviderGtk& operator=(const WindowFrameProviderGtk&) = delete;
|
||||
@@ -69,6 +69,9 @@ class WindowFrameProviderGtk : public ui::WindowFrameProvider {
|
||||
|
||||
// Cached bitmaps and metrics. The scale is rounded to percent.
|
||||
base::flat_map<int, Asset> assets_;
|
||||
+
|
||||
+ // Whether to draw the window decorations as maximized.
|
||||
+ bool maximized_;
|
||||
};
|
||||
|
||||
} // namespace gtk
|
||||
diff --git a/ui/linux/linux_ui.h b/ui/linux/linux_ui.h
|
||||
index 0cd8a0e101de186e11ead65526c7f0abc60c6577..7db580ce04a407877ca4108ec087120cdb9ce2ad 100644
|
||||
--- a/ui/linux/linux_ui.h
|
||||
+++ b/ui/linux/linux_ui.h
|
||||
@@ -176,7 +176,7 @@ class COMPONENT_EXPORT(LINUX_UI) LinuxUi
|
||||
// if transparency is unsupported and the frame should be rendered opaque.
|
||||
// The returned object is not owned by the caller and will remain alive until
|
||||
// the process ends.
|
||||
- virtual WindowFrameProvider* GetWindowFrameProvider(bool solid_frame) = 0;
|
||||
+ virtual WindowFrameProvider* GetWindowFrameProvider(bool solid_frame, bool maximized) = 0;
|
||||
|
||||
// Returns a map of KeyboardEvent code to KeyboardEvent key values.
|
||||
virtual base::flat_map<std::string, std::string> GetKeyboardLayoutMap() = 0;
|
||||
@@ -6,10 +6,10 @@ Subject: allow disabling blink scheduler throttling per RenderView
|
||||
This allows us to disable throttling for hidden windows.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
|
||||
index 261e1dda1e128e22d15f3454f9012265db45bd74..98b130f0791d1ca2d59ef62151df7e60f3f40831 100644
|
||||
index 1f6d9be10432416f591a616805494b5d78975df1..e73f70c62ac2e69c918bdf39bd53f74a47066f4e 100644
|
||||
--- a/content/browser/renderer_host/render_view_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_view_host_impl.cc
|
||||
@@ -666,6 +666,11 @@ void RenderViewHostImpl::SetBackgroundOpaque(bool opaque) {
|
||||
@@ -665,6 +665,11 @@ void RenderViewHostImpl::SetBackgroundOpaque(bool opaque) {
|
||||
GetWidget()->GetAssociatedFrameWidget()->SetBackgroundOpaque(opaque);
|
||||
}
|
||||
|
||||
@@ -48,18 +48,18 @@ index 4d2a4c6746e1dbfc619faf2e16eaa4948d74e372..6c9f190ff595234eca18ff20ca0655da
|
||||
// This interface should only be implemented inside content.
|
||||
friend class RenderViewHostImpl;
|
||||
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
|
||||
index 2f073474d8be6d8051606b0f07272969d3936f28..7f9ec06a10b4cba254737fabdc38dddf86137ad7 100644
|
||||
index 99978b33c294ebe37192baccb29f0a34a25aed17..ef6e9ae24979538b8746aca898d1f302827491d8 100644
|
||||
--- a/content/renderer/render_view_impl.h
|
||||
+++ b/content/renderer/render_view_impl.h
|
||||
@@ -147,6 +147,8 @@ class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient {
|
||||
bool was_created_by_renderer,
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
|
||||
|
||||
+ void OnSetSchedulerThrottling(bool allowed);
|
||||
+
|
||||
@@ -151,6 +151,8 @@ class CONTENT_EXPORT RenderViewImpl : public blink::WebViewClient,
|
||||
static WindowOpenDisposition NavigationPolicyToDisposition(
|
||||
blink::WebNavigationPolicy policy);
|
||||
|
||||
+ void OnSetSchedulerThrottling(bool allowed);
|
||||
+
|
||||
// ---------------------------------------------------------------------------
|
||||
// ADDING NEW FUNCTIONS? Please keep private functions alphabetized and put
|
||||
// it in the same order in the .cc file as it was in the header.
|
||||
diff --git a/third_party/blink/public/mojom/page/page.mojom b/third_party/blink/public/mojom/page/page.mojom
|
||||
index 39bfc2200e924d0c589cfd07f085f182ef6853a6..bddff6d5ad3f6d08c4dc48e66ebc5319b1a5ec28 100644
|
||||
--- a/third_party/blink/public/mojom/page/page.mojom
|
||||
@@ -73,10 +73,10 @@ index 39bfc2200e924d0c589cfd07f085f182ef6853a6..bddff6d5ad3f6d08c4dc48e66ebc5319
|
||||
+ SetSchedulerThrottling(bool allowed);
|
||||
};
|
||||
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h
|
||||
index b01562ebe042bd23e7b5184aa28bb42f98f81ecb..5392b5ac0f95eab7fef3c59fd2e9b2dc2cfb7342 100644
|
||||
index 5e4032ccf916f969cd669af7d983becddb57c72b..a858c9f2fa609ae756a2e70d0362f2de372dd5be 100644
|
||||
--- a/third_party/blink/public/web/web_view.h
|
||||
+++ b/third_party/blink/public/web/web_view.h
|
||||
@@ -361,6 +361,7 @@ class WebView {
|
||||
@@ -364,6 +364,7 @@ class WebView {
|
||||
// Scheduling -----------------------------------------------------------
|
||||
|
||||
virtual PageScheduler* Scheduler() const = 0;
|
||||
@@ -85,10 +85,10 @@ index b01562ebe042bd23e7b5184aa28bb42f98f81ecb..5392b5ac0f95eab7fef3c59fd2e9b2dc
|
||||
// Visibility -----------------------------------------------------------
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
|
||||
index 390e47422a0a106d0e5746c0af0611d420af8025..9151815e6bf33a3a6980f8337f578dc90e458696 100644
|
||||
index 229d9f2112e70f3bbff6e6986ab01c67483a1ae9..0529b4399959a2a2b9b0131dd8736a87fb973b0b 100644
|
||||
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
|
||||
@@ -3742,6 +3742,13 @@ PageScheduler* WebViewImpl::Scheduler() const {
|
||||
@@ -3711,6 +3711,13 @@ PageScheduler* WebViewImpl::Scheduler() const {
|
||||
return GetPage()->GetPageScheduler();
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ index 390e47422a0a106d0e5746c0af0611d420af8025..9151815e6bf33a3a6980f8337f578dc9
|
||||
void WebViewImpl::SetVisibilityState(
|
||||
mojom::blink::PageVisibilityState visibility_state,
|
||||
bool is_initial_state) {
|
||||
@@ -3753,7 +3760,8 @@ void WebViewImpl::SetVisibilityState(
|
||||
@@ -3722,7 +3729,8 @@ void WebViewImpl::SetVisibilityState(
|
||||
}
|
||||
GetPage()->SetVisibilityState(visibility_state, is_initial_state);
|
||||
GetPage()->GetPageScheduler()->SetPageVisible(
|
||||
@@ -113,10 +113,10 @@ index 390e47422a0a106d0e5746c0af0611d420af8025..9151815e6bf33a3a6980f8337f578dc9
|
||||
|
||||
mojom::blink::PageVisibilityState WebViewImpl::GetVisibilityState() {
|
||||
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
|
||||
index ce3a483a4c06dc56a8a71d32d4d4a7077d524c2e..1cab34e52858808bceb52556c7ad0bbaa7584225 100644
|
||||
index 2f8e971ab224b36c6e464eb7524dd3d4c6b76f8c..4a9664d0ce5de431d9638e4145a21091cea78fd1 100644
|
||||
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
|
||||
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
|
||||
@@ -417,6 +417,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
|
||||
@@ -418,6 +418,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
|
||||
LocalDOMWindow* PagePopupWindow() const;
|
||||
|
||||
PageScheduler* Scheduler() const override;
|
||||
@@ -124,7 +124,7 @@ index ce3a483a4c06dc56a8a71d32d4d4a7077d524c2e..1cab34e52858808bceb52556c7ad0bba
|
||||
void SetVisibilityState(mojom::blink::PageVisibilityState visibility_state,
|
||||
bool is_initial_state) override;
|
||||
mojom::blink::PageVisibilityState GetVisibilityState() override;
|
||||
@@ -864,6 +865,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
|
||||
@@ -865,6 +866,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
|
||||
// If true, we send IPC messages when |preferred_size_| changes.
|
||||
bool send_preferred_size_changes_ = false;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: allow new privileges in unsandboxed child processes
|
||||
This allows unsandboxed renderers to launch setuid processes on Linux.
|
||||
|
||||
diff --git a/content/browser/child_process_launcher_helper_linux.cc b/content/browser/child_process_launcher_helper_linux.cc
|
||||
index 16d838b710d4f717733f4aa8f92f144922969b3b..ff2c78c7b803159dde97dafdb799d9b8761dc3fd 100644
|
||||
index b2b29e715d6e5ea427faf6829e935e91dd87d471..138b5da2e5ae85760faaeeff92168d1070b6f562 100644
|
||||
--- a/content/browser/child_process_launcher_helper_linux.cc
|
||||
+++ b/content/browser/child_process_launcher_helper_linux.cc
|
||||
@@ -54,6 +54,18 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: Allow setting secondary label via SimpleMenuModel
|
||||
Builds on https://chromium-review.googlesource.com/c/chromium/src/+/2208976
|
||||
|
||||
diff --git a/ui/base/models/simple_menu_model.cc b/ui/base/models/simple_menu_model.cc
|
||||
index 20a3b1efcb52be5e10dc184df620ec8102f2aff3..dfebc65b2ce180e4cd175ab8d09ad7e16f6b8df5 100644
|
||||
index a787411f89e2d95e2fa636a7cc6723bdd227e563..f8c67d10957c26fbcd21fa1fe05507efd78f1c29 100644
|
||||
--- a/ui/base/models/simple_menu_model.cc
|
||||
+++ b/ui/base/models/simple_menu_model.cc
|
||||
@@ -53,6 +53,11 @@ std::u16string SimpleMenuModel::Delegate::GetLabelForCommandId(
|
||||
@@ -47,7 +47,7 @@ index 20a3b1efcb52be5e10dc184df620ec8102f2aff3..dfebc65b2ce180e4cd175ab8d09ad7e1
|
||||
return items_[ValidateItemIndex(index)].minor_text;
|
||||
}
|
||||
diff --git a/ui/base/models/simple_menu_model.h b/ui/base/models/simple_menu_model.h
|
||||
index eadda341710f3a2e35f0e5c6aeb65a0dcc7bf0dd..2a7cbfa33702b9a5b89d1e69d5e8d0af83735bd7 100644
|
||||
index bd2ebaf9f84946c708eba13c18869afadd2fdbb0..880d6f12ad188c5f8abf037b3b8d27fcf1fc2cb6 100644
|
||||
--- a/ui/base/models/simple_menu_model.h
|
||||
+++ b/ui/base/models/simple_menu_model.h
|
||||
@@ -49,6 +49,7 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel {
|
||||
|
||||
@@ -7,10 +7,10 @@ This is used by editors to obtain the filesystem path from a dragged file. See
|
||||
documentation at https://electronjs.org/docs/api/file-object
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/fileapi/file.h b/third_party/blink/renderer/core/fileapi/file.h
|
||||
index c061962bec620d2da0e217d8f55b7db57d120f97..59d9946ecfb7d68b41f539ce7c29c7398e00e9b2 100644
|
||||
index 72d6b7e109779c9785130ebb0e1e23202c5bc68d..e12c4acfd87f1d698d7c8c8459e7231ee03789fd 100644
|
||||
--- a/third_party/blink/renderer/core/fileapi/file.h
|
||||
+++ b/third_party/blink/renderer/core/fileapi/file.h
|
||||
@@ -211,6 +211,9 @@ class CORE_EXPORT File final : public Blob {
|
||||
@@ -212,6 +212,9 @@ class CORE_EXPORT File final : public Blob {
|
||||
}
|
||||
const String& name() const { return name_; }
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@ Refs changes in:
|
||||
This patch reverts the changes to fix associated crashes in Electron.
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/frame/frame.cc b/third_party/blink/renderer/core/frame/frame.cc
|
||||
index 1ced95928589b38d76df1c460df7712e8e8c1611..2977ba7ce2f6a102f04bd9ad591fc583fd836051 100644
|
||||
index f370d230361c3ab524c0fc74facf8954840aa29f..0e62d29e44a971d49d70e485509d0b59f5cb31c7 100644
|
||||
--- a/third_party/blink/renderer/core/frame/frame.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/frame.cc
|
||||
@@ -124,14 +124,6 @@ bool Frame::Detach(FrameDetachType type) {
|
||||
@@ -123,14 +123,6 @@ bool Frame::Detach(FrameDetachType type) {
|
||||
|
||||
DCHECK(!IsDetached());
|
||||
|
||||
@@ -33,7 +33,7 @@ index 1ced95928589b38d76df1c460df7712e8e8c1611..2977ba7ce2f6a102f04bd9ad591fc583
|
||||
if (type == FrameDetachType::kRemove) {
|
||||
if (provisional_frame_) {
|
||||
provisional_frame_->Detach(FrameDetachType::kRemove);
|
||||
@@ -155,6 +147,14 @@ bool Frame::Detach(FrameDetachType type) {
|
||||
@@ -154,6 +146,14 @@ bool Frame::Detach(FrameDetachType type) {
|
||||
GetWindowProxyManager()->ClearForSwap();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ index 1ced95928589b38d76df1c460df7712e8e8c1611..2977ba7ce2f6a102f04bd9ad591fc583
|
||||
// its owning reference back to our owning LocalFrame.
|
||||
client_->Detached(type);
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
|
||||
index 5fccf35dfef38989bd68c69cfc35ac5d716ec165..dc45af36b30091b98cb37c927abd9a294c27bb71 100644
|
||||
index d5ef00cb9870c2dc767d80595a39af4302c3e3c3..f3a2a9527f97902f357782eb445cf63777c77398 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
|
||||
@@ -544,10 +544,6 @@ bool LocalFrame::DetachImpl(FrameDetachType type) {
|
||||
|
||||
@@ -10,7 +10,7 @@ breakpad independently, as a "browser" process. This patches
|
||||
crash annotation.
|
||||
|
||||
diff --git a/components/crash/core/app/breakpad_linux.cc b/components/crash/core/app/breakpad_linux.cc
|
||||
index 1fa85302da7a64abc42fd9558ddbcaf68b387517..62d15f57e4c5a0a24aa730e8979fb1e9537fecd3 100644
|
||||
index 3933fa761768b5a45891bfef4c2c2123b92fc276..2eb52b71d7ebc7525cceffbecc99db6751429afd 100644
|
||||
--- a/components/crash/core/app/breakpad_linux.cc
|
||||
+++ b/components/crash/core/app/breakpad_linux.cc
|
||||
@@ -719,8 +719,13 @@ bool CrashDone(const MinidumpDescriptor& minidump,
|
||||
|
||||
@@ -9,7 +9,7 @@ and can be removed when the crash in fork is resolved.
|
||||
Related issue: https://github.com/electron/electron/issues/32718
|
||||
|
||||
diff --git a/base/allocator/allocator.gni b/base/allocator/allocator.gni
|
||||
index c3c62f83553bd0d258de4d5d9ecd8b02a74f594b..3dbf4462fa056db7a4084453ef35f1b944fbd093 100644
|
||||
index 97a57dfb1626ae9a781736dd8b0b55bf201162c1..5c97441faad781b459255cb1f7d0652ec86e40c8 100644
|
||||
--- a/base/allocator/allocator.gni
|
||||
+++ b/base/allocator/allocator.gni
|
||||
@@ -20,7 +20,7 @@ _disable_partition_alloc = is_component_build || (is_win && is_debug)
|
||||
|
||||
@@ -13,7 +13,7 @@ This patch can be removed when enable_print_content_analysis can be more
|
||||
easily enabled or disabled by default with buildflags.
|
||||
|
||||
diff --git a/printing/buildflags/buildflags.gni b/printing/buildflags/buildflags.gni
|
||||
index 1d2b24adbb39215531bbe189d6191dba026d4f68..88b7962836cfe93a59d1569245f4815f22be355e 100644
|
||||
index 559ac76d4e4b9d9c1824c4da186a6b0f7619fcca..72855e0c5fadb286b67144b34ff71f45e1434c73 100644
|
||||
--- a/printing/buildflags/buildflags.gni
|
||||
+++ b/printing/buildflags/buildflags.gni
|
||||
@@ -36,8 +36,7 @@ declare_args() {
|
||||
|
||||
@@ -11,7 +11,7 @@ if we ever align our .pak file generation with Chrome we can remove this
|
||||
patch.
|
||||
|
||||
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
|
||||
index a9e0afc645b8bd543590e80b55a7461381373187..3d2e799541e26f5e421e20ccaff65020687314c2 100644
|
||||
index dc59a88bc930d4d7b8e606434d940cac5b834bd0..6a583029436f033dc2736b9d7407f26637936add 100644
|
||||
--- a/chrome/BUILD.gn
|
||||
+++ b/chrome/BUILD.gn
|
||||
@@ -175,11 +175,16 @@ if (!is_android && !is_mac) {
|
||||
@@ -33,10 +33,10 @@ index a9e0afc645b8bd543590e80b55a7461381373187..3d2e799541e26f5e421e20ccaff65020
|
||||
"//base",
|
||||
"//build:branding_buildflags",
|
||||
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
|
||||
index 244373ba428ada917929c5161eb2c75ef1ccf8d3..556a613a6697eeea6b15894449fec884b97ec8b5 100644
|
||||
index 79aa50fbb9944052163bfdf958c5add60a0151f8..9fce5f07a79f801253c6bd8658ed7dba902856ad 100644
|
||||
--- a/chrome/browser/BUILD.gn
|
||||
+++ b/chrome/browser/BUILD.gn
|
||||
@@ -4574,7 +4574,7 @@ static_library("browser") {
|
||||
@@ -4479,7 +4479,7 @@ static_library("browser") {
|
||||
|
||||
# On Windows, the hashes are embedded in //chrome:chrome_initial rather
|
||||
# than here in :chrome_dll.
|
||||
@@ -46,18 +46,18 @@ index 244373ba428ada917929c5161eb2c75ef1ccf8d3..556a613a6697eeea6b15894449fec884
|
||||
sources += [ "certificate_viewer_stub.cc" ]
|
||||
}
|
||||
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
|
||||
index 8c1a1b9c39a4ba00784ef91aaa81bf2453ac13e6..95e2f70445568d95351e8b1b5da71dc8e85e46cd 100644
|
||||
index 65bee9c9d02c6f95cce6ba60d69e2a1b879a1c2f..e26897337f8c96a493936ab1342eb6b7c2c63ffe 100644
|
||||
--- a/chrome/test/BUILD.gn
|
||||
+++ b/chrome/test/BUILD.gn
|
||||
@@ -5963,7 +5963,6 @@ test("unit_tests") {
|
||||
@@ -5870,7 +5870,6 @@ test("unit_tests") {
|
||||
|
||||
deps += [
|
||||
"//chrome:other_version",
|
||||
- "//chrome:packed_resources_integrity",
|
||||
"//chrome//services/util_win:unit_tests",
|
||||
"//chrome/app:chrome_dll_resources",
|
||||
"//chrome/app:crash_reporter_client_win_unit_tests",
|
||||
@@ -5988,6 +5987,10 @@ test("unit_tests") {
|
||||
"//chrome/browser:chrome_process_finder",
|
||||
@@ -5893,6 +5892,10 @@ test("unit_tests") {
|
||||
"//ui/resources",
|
||||
]
|
||||
|
||||
@@ -68,16 +68,15 @@ index 8c1a1b9c39a4ba00784ef91aaa81bf2453ac13e6..95e2f70445568d95351e8b1b5da71dc8
|
||||
ldflags = [
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-error-l1-1-0.dll",
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll",
|
||||
@@ -6879,7 +6882,7 @@ test("unit_tests") {
|
||||
@@ -6786,7 +6789,6 @@ test("unit_tests") {
|
||||
}
|
||||
|
||||
deps += [
|
||||
- "//chrome:packed_resources_integrity_hash",
|
||||
+ # "//chrome:packed_resources_integrity_hash",
|
||||
"//chrome/browser/enterprise/connectors/analysis:features",
|
||||
"//chrome/browser:cart_db_content_proto",
|
||||
"//chrome/browser:coupon_db_content_proto",
|
||||
"//chrome/browser/media/router:test_support",
|
||||
"//chrome/browser/media/router/discovery:discovery",
|
||||
@@ -6993,6 +6996,10 @@ test("unit_tests") {
|
||||
@@ -6887,6 +6889,10 @@ test("unit_tests") {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ tradeoff is that switching from MAS_BUILD to !MAS_BUILD or vice-versa will
|
||||
rebuild the entire tree.
|
||||
|
||||
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
|
||||
index c737e53c2ce7237974f6c749eae60ba1de7ec2c1..26ba3ae4a77bc8f525c2ad927ff2956c028ef337 100644
|
||||
index d960648941d8b959b25f87b364a594ec44760348..74a14a2373305e2e62b974b34a28ea9a62c6a911 100644
|
||||
--- a/build/config/BUILDCONFIG.gn
|
||||
+++ b/build/config/BUILDCONFIG.gn
|
||||
@@ -123,6 +123,9 @@ if (current_os == "") {
|
||||
@@ -27,7 +27,7 @@ index c737e53c2ce7237974f6c749eae60ba1de7ec2c1..26ba3ae4a77bc8f525c2ad927ff2956c
|
||||
# Set to enable the official build level of optimization. This has nothing
|
||||
# to do with branding, but enables an additional level of optimization above
|
||||
# release (!is_debug). This might be better expressed as a tri-state
|
||||
@@ -348,6 +351,7 @@ default_compiler_configs = [
|
||||
@@ -349,6 +352,7 @@ default_compiler_configs = [
|
||||
"//build/config/compiler/pgo:default_pgo_flags",
|
||||
"//build/config/coverage:default_coverage",
|
||||
"//build/config/sanitizers:default_sanitizer_flags",
|
||||
|
||||
@@ -7,7 +7,7 @@ Build libc++ as static library to compile and pass
|
||||
nan tests
|
||||
|
||||
diff --git a/buildtools/third_party/libc++/BUILD.gn b/buildtools/third_party/libc++/BUILD.gn
|
||||
index b3e5378f711c54b76c73179e791646d4e5e4e96b..262c8e53ec25b2e91a73b5971d64dbe5d5e005a1 100644
|
||||
index 74b6ad644d49c003996db0eab225ea30ac17420a..0a1ba3510be3047bfc34e603c5aaafbf15908269 100644
|
||||
--- a/buildtools/third_party/libc++/BUILD.gn
|
||||
+++ b/buildtools/third_party/libc++/BUILD.gn
|
||||
@@ -44,7 +44,11 @@ config("winver") {
|
||||
|
||||
@@ -6,23 +6,18 @@ Subject: build: make libcxx_abi_unstable false for electron
|
||||
https://nornagon.medium.com/a-libc-odyssey-973e51649063
|
||||
|
||||
diff --git a/build/config/c++/BUILD.gn b/build/config/c++/BUILD.gn
|
||||
index 09324583a2f98621fe328ec9f0178736dabe6d2b..d57c2c16ea3475c3ad77e81bdb9700ec2f64976a 100644
|
||||
index 046792ac275853bf109537589b911cfada44ed24..e43daeaa8f8c8e23eea99b3f8f5f48f92012bbc1 100644
|
||||
--- a/build/config/c++/BUILD.gn
|
||||
+++ b/build/config/c++/BUILD.gn
|
||||
@@ -29,10 +29,12 @@ config("runtime_library") {
|
||||
# on Windows, the increase is great enough that we go above the 4GB size
|
||||
# limit for PDBs (https://crbug.com/1327710#c5). To fix this, we set
|
||||
# _LIBCPP_ABI_NAMESPACE to a shorter value.
|
||||
- defines += [
|
||||
- "_LIBCPP_ABI_NAMESPACE=Cr",
|
||||
- "_LIBCPP_ABI_VERSION=2",
|
||||
- ]
|
||||
+ defines += [ "_LIBCPP_ABI_NAMESPACE=Cr" ]
|
||||
+
|
||||
+ if (!is_electron_build) {
|
||||
+ # This breaks native node modules
|
||||
+ defines += [ "_LIBCPP_ABI_VERSION=2" ]
|
||||
+ }
|
||||
@@ -8,6 +8,11 @@ assert(use_custom_libcxx, "should only be used if use_custom_libcxx is set")
|
||||
|
||||
if (!libcxx_is_shared) {
|
||||
# Don't leak any symbols on a static build.
|
||||
libcxx_abi_unstable = true
|
||||
|
||||
+if (is_electron_build) {
|
||||
+ # This breaks native node modules
|
||||
+ libcxx_abi_unstable = false
|
||||
+}
|
||||
+
|
||||
# TODO(xiaohuic): https://crbug/917533 Crashes on internal ChromeOS build.
|
||||
# Do unconditionally once the underlying problem is fixed.
|
||||
if (is_chromeos_ash && is_chrome_branded) {
|
||||
|
||||
@@ -9,10 +9,10 @@ potentially prevent a window from being created.
|
||||
TODO(loc): this patch is currently broken.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index bdfc0719057218afeb61fec8f4e75298c3baa54c..9c6f51f1667d9bf1b430a83747faebf633a324c7 100644
|
||||
index c983b5f4c20acba8a7d779a634cd1593ef69b1ae..e612764997277da3411d8040850756eb38996cca 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -7283,6 +7283,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
@@ -6922,6 +6922,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
last_committed_origin_, params->window_container_type,
|
||||
params->target_url, params->referrer.To<Referrer>(),
|
||||
params->frame_name, params->disposition, *params->features,
|
||||
@@ -21,10 +21,10 @@ index bdfc0719057218afeb61fec8f4e75298c3baa54c..9c6f51f1667d9bf1b430a83747faebf6
|
||||
&no_javascript_access);
|
||||
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 860e52ddb3db1ccc38a7ef6e11acc0da67c98ac5..14bc2c9e77b7db69d03c00314fe55806d2a9e38c 100644
|
||||
index b94e87b6f90c986f115a87baf8214baeb8103826..987e437641b7978290aa2633755b67f9099e1d04 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -3990,6 +3990,14 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
@@ -3912,6 +3912,14 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
}
|
||||
auto* new_contents_impl = new_contents.get();
|
||||
|
||||
@@ -39,7 +39,7 @@ index 860e52ddb3db1ccc38a7ef6e11acc0da67c98ac5..14bc2c9e77b7db69d03c00314fe55806
|
||||
new_contents_impl->GetController().SetSessionStorageNamespace(
|
||||
partition_config, session_storage_namespace);
|
||||
|
||||
@@ -4034,12 +4042,6 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
@@ -3956,12 +3964,6 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
AddWebContentsDestructionObserver(new_contents_impl);
|
||||
}
|
||||
|
||||
@@ -53,13 +53,13 @@ index 860e52ddb3db1ccc38a7ef6e11acc0da67c98ac5..14bc2c9e77b7db69d03c00314fe55806
|
||||
new_contents_impl, opener, params.target_url,
|
||||
params.referrer.To<Referrer>(), params.disposition,
|
||||
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
|
||||
index cc492885ec8ae5577c6e8702dc30749331332103..c852b894f976304e6b20908a6e66ccd698887604 100644
|
||||
index 5aca51ea4154941512e989048295c7de0475c14c..278accd8c6f14a4d91cc2ff4e336e365279c7b9b 100644
|
||||
--- a/content/common/frame.mojom
|
||||
+++ b/content/common/frame.mojom
|
||||
@@ -587,6 +587,10 @@ struct CreateNewWindowParams {
|
||||
@@ -569,6 +569,10 @@ struct CreateNewWindowParams {
|
||||
|
||||
// Additional parameters for creating picture-in-picture windows.
|
||||
blink.mojom.PictureInPictureWindowOptions? pip_options;
|
||||
// Governs how downloads are handled if `target_url` results in a download.
|
||||
blink.mojom.NavigationDownloadPolicy download_policy;
|
||||
+
|
||||
+ // Extra fields added by Electron.
|
||||
+ string raw_features;
|
||||
@@ -68,10 +68,10 @@ index cc492885ec8ae5577c6e8702dc30749331332103..c852b894f976304e6b20908a6e66ccd6
|
||||
|
||||
// Operation result when the renderer asks the browser to create a new window.
|
||||
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
|
||||
index 15620fd7b5d95eb031641e0eeb6d4c2ec74071d2..8f75315f0d4ba45314be5d2d88a417b44ba2c254 100644
|
||||
index 82d33875526759dda05a1818543c0605382597f4..ec89c920f0e0ad3638749b1468bcd54f74b3cce5 100644
|
||||
--- a/content/public/browser/content_browser_client.cc
|
||||
+++ b/content/public/browser/content_browser_client.cc
|
||||
@@ -617,6 +617,8 @@ bool ContentBrowserClient::CanCreateWindow(
|
||||
@@ -594,6 +594,8 @@ bool ContentBrowserClient::CanCreateWindow(
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::mojom::WindowFeatures& features,
|
||||
@@ -81,7 +81,7 @@ index 15620fd7b5d95eb031641e0eeb6d4c2ec74071d2..8f75315f0d4ba45314be5d2d88a417b4
|
||||
bool opener_suppressed,
|
||||
bool* no_javascript_access) {
|
||||
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
|
||||
index cadbd44a85b6117cd001c1dec120d18520ff2855..e0bfafe859b600ac5033f78d1eb5823ddda956c4 100644
|
||||
index e2c88a7e692406c9774a0e9783df612cbc38d7cd..4e069af9256eb106b50e84d1243c92353daf2015 100644
|
||||
--- a/content/public/browser/content_browser_client.h
|
||||
+++ b/content/public/browser/content_browser_client.h
|
||||
@@ -165,6 +165,7 @@ class NetworkService;
|
||||
@@ -92,7 +92,7 @@ index cadbd44a85b6117cd001c1dec120d18520ff2855..e0bfafe859b600ac5033f78d1eb5823d
|
||||
} // namespace network
|
||||
|
||||
namespace sandbox {
|
||||
@@ -993,6 +994,8 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
@@ -968,6 +969,8 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::mojom::WindowFeatures& features,
|
||||
@@ -102,7 +102,7 @@ index cadbd44a85b6117cd001c1dec120d18520ff2855..e0bfafe859b600ac5033f78d1eb5823d
|
||||
bool opener_suppressed,
|
||||
bool* no_javascript_access);
|
||||
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
|
||||
index ef3889063b562a37fbd945fe30db0d776ecaee7a..99e8449e9c515dd70ed88546a71f83ae139178fe 100644
|
||||
index daf9b4566396c6d681760329cf4ba6869bbb55e4..321d5cfc36e40f2a649e8ea5910f4082b71b62e1 100644
|
||||
--- a/content/public/browser/web_contents_delegate.cc
|
||||
+++ b/content/public/browser/web_contents_delegate.cc
|
||||
@@ -26,6 +26,17 @@ namespace content {
|
||||
@@ -124,7 +124,7 @@ index ef3889063b562a37fbd945fe30db0d776ecaee7a..99e8449e9c515dd70ed88546a71f83ae
|
||||
const OpenURLParams& params) {
|
||||
return nullptr;
|
||||
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
|
||||
index b088cb301003359fefad0ea9ca42b96f0cf3de6c..eec7bf18d17e85bde8017d4c8e7f064987b4d4d3 100644
|
||||
index 04aa4d993b331396ee20464f6e1d2da10c91c834..2556c044b6e28501a5fac9b0040e623b8f35f497 100644
|
||||
--- a/content/public/browser/web_contents_delegate.h
|
||||
+++ b/content/public/browser/web_contents_delegate.h
|
||||
@@ -16,6 +16,7 @@
|
||||
@@ -150,10 +150,18 @@ index b088cb301003359fefad0ea9ca42b96f0cf3de6c..eec7bf18d17e85bde8017d4c8e7f0649
|
||||
// typically happens when popups are created.
|
||||
virtual void WebContentsCreated(WebContents* source_contents,
|
||||
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
|
||||
index 913b3647c4632b580fa1551f4ebfeaca6f9fe17e..9cc6a793a1ec3e53db1ef31aec37c569695b197e 100644
|
||||
index 03b637c4d3a68a2bff5a4e06f421f23f97f40911..6235fd626a377643851dbb98d4d089e5a59366db 100644
|
||||
--- a/content/renderer/render_view_impl.cc
|
||||
+++ b/content/renderer/render_view_impl.cc
|
||||
@@ -315,6 +315,10 @@ WebView* RenderViewImpl::CreateView(
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "third_party/blink/public/mojom/page/page.mojom.h"
|
||||
#include "third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h"
|
||||
#include "third_party/blink/public/platform/url_conversion.h"
|
||||
+#include "third_party/blink/public/platform/web_url_request_util.h"
|
||||
#include "third_party/blink/public/web/modules/mediastream/web_media_stream_device_observer.h"
|
||||
#include "third_party/blink/public/web/web_frame_widget.h"
|
||||
#include "third_party/blink/public/web/web_local_frame.h"
|
||||
@@ -302,6 +303,10 @@ WebView* RenderViewImpl::CreateView(
|
||||
/*openee_can_access_opener_origin=*/true, !creator->IsAllowedToDownload(),
|
||||
creator->IsAdSubframe());
|
||||
|
||||
@@ -165,10 +173,10 @@ index 913b3647c4632b580fa1551f4ebfeaca6f9fe17e..9cc6a793a1ec3e53db1ef31aec37c569
|
||||
// moved on send.
|
||||
bool is_background_tab =
|
||||
diff --git a/content/web_test/browser/web_test_content_browser_client.cc b/content/web_test/browser/web_test_content_browser_client.cc
|
||||
index d6dd69c53b66a89ea63927319d7b385f91921ea2..71748596f4d05de73263ed11b122d75a38b49616 100644
|
||||
index 2e7c332565ebe33b00ab7fff96a6a8dfc61422a6..0ab061f51d1d0c93f23bfcf5ba051172cea37eb8 100644
|
||||
--- a/content/web_test/browser/web_test_content_browser_client.cc
|
||||
+++ b/content/web_test/browser/web_test_content_browser_client.cc
|
||||
@@ -440,6 +440,8 @@ bool WebTestContentBrowserClient::CanCreateWindow(
|
||||
@@ -438,6 +438,8 @@ bool WebTestContentBrowserClient::CanCreateWindow(
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::mojom::WindowFeatures& features,
|
||||
@@ -178,10 +186,10 @@ index d6dd69c53b66a89ea63927319d7b385f91921ea2..71748596f4d05de73263ed11b122d75a
|
||||
bool opener_suppressed,
|
||||
bool* no_javascript_access) {
|
||||
diff --git a/content/web_test/browser/web_test_content_browser_client.h b/content/web_test/browser/web_test_content_browser_client.h
|
||||
index 4805dd035772fcaea60a1a91eb9911d5c0ce93a9..3b752ea509149f04fd6d10f6977bd29791f6a5d6 100644
|
||||
index 00e2a8c21d4f0ef00c942498251fa44065da63c0..0fc4b092fa276063e05f990bf920fecd60c6d26c 100644
|
||||
--- a/content/web_test/browser/web_test_content_browser_client.h
|
||||
+++ b/content/web_test/browser/web_test_content_browser_client.h
|
||||
@@ -81,6 +81,8 @@ class WebTestContentBrowserClient : public ShellContentBrowserClient {
|
||||
@@ -80,6 +80,8 @@ class WebTestContentBrowserClient : public ShellContentBrowserClient {
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::mojom::WindowFeatures& features,
|
||||
@@ -212,15 +220,14 @@ index 34570168ccb123f5102dcf8fa6bbf98e7c373ec6..192701e56d258da41b3724292853885e
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
index ec10f16c6e6c5507ad2fb0afe306a744885eb58e..3f7a069c3f1b8412074864eb99bf47469a699837 100644
|
||||
index a25203186cc2df437fe3f9fe309599d86284aefb..b288472c5a00d76077859f02c0e1abca826aa8be 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
@@ -2084,6 +2084,8 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
|
||||
WebWindowFeatures window_features =
|
||||
GetWindowFeaturesFromString(features, entered_window);
|
||||
@@ -2093,6 +2093,7 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
|
||||
|
||||
WebWindowFeatures window_features =
|
||||
GetWindowFeaturesFromString(features, incumbent_window);
|
||||
+ window_features.raw_features = features;
|
||||
+
|
||||
|
||||
// In fenced frames, we should always use `noopener`.
|
||||
if (GetFrame()->IsInFencedFrameTree()) {
|
||||
window_features.noopener = true;
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <sattard@salesforce.com>
|
||||
Date: Tue, 26 Jul 2022 00:05:29 -0700
|
||||
Subject: chore: add electron deps to gitignores
|
||||
|
||||
Makes things like "git status" quicker when developing electron locally
|
||||
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index d68a1b2dd91704a00be9cce6ccfa5daf7da35e1a..ab30dd802543491352d3b407f12127c04742d1ab 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -229,6 +229,7 @@ vs-chromium-project.txt
|
||||
/delegate_execute
|
||||
/device/serial/device_serial_mojo.xml
|
||||
/docs/website
|
||||
+/electron
|
||||
/google_apis/gcm/gcm.xml
|
||||
/google_apis/internal
|
||||
/googleurl
|
||||
diff --git a/third_party/.gitignore b/third_party/.gitignore
|
||||
index 63611fc675a17af16dc20cbd9b20e28db63a7ead..eb369ac8b3bc0c2344491438b67e1618d2efb244 100644
|
||||
--- a/third_party/.gitignore
|
||||
+++ b/third_party/.gitignore
|
||||
@@ -83,6 +83,7 @@
|
||||
/directxsdk
|
||||
/dom_distiller_js/dist
|
||||
/eigen3/src
|
||||
+/electron_node
|
||||
/elfutils/src
|
||||
/emoji-segmenter/src
|
||||
/emoji-metadata/src
|
||||
@@ -179,6 +180,7 @@
|
||||
/mocha
|
||||
/mockito/src
|
||||
/nacl_sdk_binaries/
|
||||
+/nan
|
||||
/nasm
|
||||
/nearby/src
|
||||
/neon_2_sse/src
|
||||
@@ -242,6 +244,7 @@
|
||||
/speex
|
||||
/sqlite/src
|
||||
/sqlite4java/lib/
|
||||
+/squirrel.mac
|
||||
/subresource-filter-ruleset/data/UnindexedRules
|
||||
/swift-format
|
||||
/swiftshader/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user